فهرست منبع

Update mpdecimal, sqlite3 and some fixes to build by make.

mingodad 10 سال پیش
والد
کامیت
1511e15cd4
51فایلهای تغییر یافته به همراه8558 افزوده شده و 3445 حذف شده
  1. 2 0
      SquiLu-ext/sq_mongoose.cpp
  2. 188 87
      SquiLu-ext/sqlite3.c
  3. 1 1
      SquiLu-ext/sqlite3.h
  4. 8 8
      SquiLu/Makefile-SquiLu
  5. 1 1
      SquiLu/sq/sq.c
  6. 33 40
      libharu/libharu.cbp
  7. 167 0
      libharu/libharu.cbp.mak
  8. 110 0
      minizip/minizip.cbp.mak
  9. 87 0
      mpdecimal/README.txt
  10. 443 367
      mpdecimal/basearith.c
  11. 104 62
      mpdecimal/basearith.h
  12. 68 72
      mpdecimal/bits.h
  13. 12 12
      mpdecimal/constants.c
  14. 8 1
      mpdecimal/constants.h
  15. 122 136
      mpdecimal/context.c
  16. 118 114
      mpdecimal/convolute.c
  17. 9 2
      mpdecimal/convolute.h
  18. 79 88
      mpdecimal/crt.c
  19. 8 1
      mpdecimal/crt.h
  20. 88 78
      mpdecimal/difradix2.c
  21. 8 1
      mpdecimal/difradix2.h
  22. 24 21
      mpdecimal/fnt.c
  23. 8 1
      mpdecimal/fnt.h
  24. 156 165
      mpdecimal/fourstep.c
  25. 8 1
      mpdecimal/fourstep.h
  26. 730 656
      mpdecimal/io.c
  27. 13 13
      mpdecimal/io.h
  28. 176 123
      mpdecimal/memory.c
  29. 8 1
      mpdecimal/memory.h
  30. 751 0
      mpdecimal/mpdecimal.32.h
  31. 751 0
      mpdecimal/mpdecimal.64.h
  32. 314 288
      mpdecimal/mpdecimal.c
  33. 136 0
      mpdecimal/mpdecimal.depend
  34. 769 6
      mpdecimal/mpdecimal.h
  35. 24 12
      mpdecimal/mpdecimal.layout
  36. 731 0
      mpdecimal/mpdecimal32vc.h
  37. 737 0
      mpdecimal/mpdecimal64vc.h
  38. 24 8
      mpdecimal/mpdecimal_build_log.html
  39. 18 15
      mpdecimal/mpsignal.c
  40. 71 58
      mpdecimal/numbertheory.c
  41. 17 11
      mpdecimal/numbertheory.h
  42. 143 148
      mpdecimal/sixstep.c
  43. 8 1
      mpdecimal/sixstep.h
  44. 172 168
      mpdecimal/transpose.c
  45. 12 5
      mpdecimal/transpose.h
  46. 375 345
      mpdecimal/typearith.h
  47. 376 328
      mpdecimal/umodarith.h
  48. 62 0
      mpdecimal/vccompat.h
  49. 48 0
      mpdecimal/vcdiv64.asm
  50. 232 0
      mpdecimal/vcstdint.h
  51. 0 0
      myaxtls/sha256.c

+ 2 - 0
SquiLu-ext/sq_mongoose.cpp

@@ -1104,7 +1104,9 @@ static HSQUIRRELVM my_new_squirrel(struct mg_context *ctx) {
 	sqext_register_base64(v);
 	sqext_register_Sq_Fpdf(v);
 	sqext_register_SQLite3(v);
+#ifdef WITH_MYSQL
 	sqext_register_MySQL(v);
+#endif
 	sqext_register_sqfs(v);
 	sqext_register_mix(v);
 	sqext_register_sq_socket(v);

+ 188 - 87
SquiLu-ext/sqlite3.c

@@ -280,7 +280,7 @@ extern "C" {
 */
 #define SQLITE_VERSION        "3.8.8"
 #define SQLITE_VERSION_NUMBER 3008008
-#define SQLITE_SOURCE_ID      "2015-02-07 15:16:35 5df02f50f8348dfde4fc15126abc7b7ef7803e69"
+#define SQLITE_SOURCE_ID      "2015-02-13 16:36:14 823ad40ccb5b51aaa0d5a48da63b465df9d0649a"
 
 /*
 ** CAPI3REF: Run-Time Library Version Numbers
@@ -11852,8 +11852,14 @@ struct Expr {
 #define EP_MemToken  0x010000 /* Need to sqlite3DbFree() Expr.zToken */
 #define EP_NoReduce  0x020000 /* Cannot EXPRDUP_REDUCE this Expr */
 #define EP_Unlikely  0x040000 /* unlikely() or likelihood() function */
-#define EP_Constant  0x080000 /* Node is a constant */
+#define EP_ConstFunc 0x080000 /* Node is a SQLITE_FUNC_CONSTANT function */
 #define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */
+#define EP_Subquery  0x200000 /* Tree contains a TK_SELECT operator */
+
+/*
+** Combinations of two or more EP_* flags
+*/
+#define EP_Propagate (EP_Collate|EP_Subquery) /* Propagate these bits up tree */
 
 /*
 ** These macros can be used to test, set, or clear bits in the 
@@ -12961,6 +12967,7 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
 SQLITE_PRIVATE void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int);
 SQLITE_PRIVATE void sqlite3ExprListSetSpan(Parse*,ExprList*,ExprSpan*);
 SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3*, ExprList*);
+SQLITE_PRIVATE u32 sqlite3ExprListFlags(const ExprList*);
 SQLITE_PRIVATE int sqlite3Init(sqlite3*, char**);
 SQLITE_PRIVATE int sqlite3InitCallback(void*, int, char**, char**);
 SQLITE_PRIVATE void sqlite3Pragma(Parse*,Token*,Token*,Token*,int);
@@ -13544,12 +13551,11 @@ SQLITE_PRIVATE void sqlite3MemJournalOpen(sqlite3_file *);
 SQLITE_PRIVATE int sqlite3MemJournalSize(void);
 SQLITE_PRIVATE int sqlite3IsMemJournal(sqlite3_file *);
 
+SQLITE_PRIVATE void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p);
 #if SQLITE_MAX_EXPR_DEPTH>0
-SQLITE_PRIVATE   void sqlite3ExprSetHeight(Parse *pParse, Expr *p);
 SQLITE_PRIVATE   int sqlite3SelectExprHeight(Select *);
 SQLITE_PRIVATE   int sqlite3ExprCheckHeight(Parse*, int);
 #else
-  #define sqlite3ExprSetHeight(x,y)
   #define sqlite3SelectExprHeight(x) 0
   #define sqlite3ExprCheckHeight(x,y)
 #endif
@@ -14694,6 +14700,9 @@ struct Vdbe {
   u32 cacheCtr;           /* VdbeCursor row cache generation counter */
   int pc;                 /* The program counter */
   int rc;                 /* Value to return */
+#ifdef SQLITE_DEBUG
+  int rcApp;              /* errcode set by sqlite3_result_error_code() */
+#endif
   u16 nResColumn;         /* Number of columns in one row of the result set */
   u8 errorAction;         /* Recovery action to do in case of an error */
   u8 minWriteFileFormat;  /* Minimum file format for writable database files */
@@ -19168,8 +19177,12 @@ static sqlite3_mutex *debugMutexAlloc(int id){
       break;
     }
     default: {
-      assert( id-2 >= 0 );
-      assert( id-2 < (int)(sizeof(aStatic)/sizeof(aStatic[0])) );
+#ifdef SQLITE_ENABLE_API_ARMOR
+      if( id-2<0 || id-2>=ArraySize(aStatic) ){
+        (void)SQLITE_MISUSE_BKPT;
+        return 0;
+      }
+#endif
       pNew = &aStatic[id-2];
       pNew->id = id;
       break;
@@ -19184,8 +19197,13 @@ static sqlite3_mutex *debugMutexAlloc(int id){
 static void debugMutexFree(sqlite3_mutex *pX){
   sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
   assert( p->cnt==0 );
-  assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
-  sqlite3_free(p);
+  if( p->id==SQLITE_MUTEX_RECURSIVE || p->id==SQLITE_MUTEX_FAST ){
+    sqlite3_free(p);
+  }else{
+#ifdef SQLITE_ENABLE_API_ARMOR
+    (void)SQLITE_MISUSE_BKPT;
+#endif
+  }
 }
 
 /*
@@ -19296,8 +19314,10 @@ SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
 */
 struct sqlite3_mutex {
   pthread_mutex_t mutex;     /* Mutex controlling the lock */
-#if SQLITE_MUTEX_NREF
+#if SQLITE_MUTEX_NREF || defined(SQLITE_ENABLE_API_ARMOR)
   int id;                    /* Mutex type */
+#endif
+#if SQLITE_MUTEX_NREF
   volatile int nRef;         /* Number of entrances */
   volatile pthread_t owner;  /* Thread that is within this mutex */
   int trace;                 /* True to trace changes */
@@ -19413,9 +19433,6 @@ static sqlite3_mutex *pthreadMutexAlloc(int iType){
         pthread_mutexattr_settype(&recursiveAttr, PTHREAD_MUTEX_RECURSIVE);
         pthread_mutex_init(&p->mutex, &recursiveAttr);
         pthread_mutexattr_destroy(&recursiveAttr);
-#endif
-#if SQLITE_MUTEX_NREF
-        p->id = iType;
 #endif
       }
       break;
@@ -19423,9 +19440,6 @@ static sqlite3_mutex *pthreadMutexAlloc(int iType){
     case SQLITE_MUTEX_FAST: {
       p = sqlite3MallocZero( sizeof(*p) );
       if( p ){
-#if SQLITE_MUTEX_NREF
-        p->id = iType;
-#endif
         pthread_mutex_init(&p->mutex, 0);
       }
       break;
@@ -19438,12 +19452,12 @@ static sqlite3_mutex *pthreadMutexAlloc(int iType){
       }
 #endif
       p = &staticMutexes[iType-2];
-#if SQLITE_MUTEX_NREF
-      p->id = iType;
-#endif
       break;
     }
   }
+#if SQLITE_MUTEX_NREF || defined(SQLITE_ENABLE_API_ARMOR)
+  if( p ) p->id = iType;
+#endif
   return p;
 }
 
@@ -19455,9 +19469,18 @@ static sqlite3_mutex *pthreadMutexAlloc(int iType){
 */
 static void pthreadMutexFree(sqlite3_mutex *p){
   assert( p->nRef==0 );
-  assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
-  pthread_mutex_destroy(&p->mutex);
-  sqlite3_free(p);
+#if SQLITE_ENABLE_API_ARMOR
+  if( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE )
+#endif
+  {
+    pthread_mutex_destroy(&p->mutex);
+    sqlite3_free(p);
+  }
+#ifdef SQLITE_ENABLE_API_ARMOR
+  else{
+    (void)SQLITE_MISUSE_BKPT;
+  }
+#endif
 }
 
 /*
@@ -20134,9 +20157,6 @@ static sqlite3_mutex *winMutexAlloc(int iType){
         return 0;
       }
 #endif
-      assert( iType-2 >= 0 );
-      assert( iType-2 < ArraySize(winMutex_staticMutexes) );
-      assert( winMutex_isInit==1 );
       p = &winMutex_staticMutexes[iType-2];
 #ifdef SQLITE_DEBUG
       p->id = iType;
@@ -20158,13 +20178,15 @@ static sqlite3_mutex *winMutexAlloc(int iType){
 */
 static void winMutexFree(sqlite3_mutex *p){
   assert( p );
-#ifdef SQLITE_DEBUG
   assert( p->nRef==0 && p->owner==0 );
-  assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
+  if( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ){
+    DeleteCriticalSection(&p->mutex);
+    sqlite3_free(p);
+  }else{
+#ifdef SQLITE_ENABLE_API_ARMOR
+    (void)SQLITE_MISUSE_BKPT;
 #endif
-  assert( winMutex_isInit==1 );
-  DeleteCriticalSection(&p->mutex);
-  sqlite3_free(p);
+  }
 }
 
 /*
@@ -22111,7 +22133,7 @@ SQLITE_API char *sqlite3_vsnprintf(int n, char *zBuf, const char *zFormat, va_li
 #ifdef SQLITE_ENABLE_API_ARMOR
   if( zBuf==0 || zFormat==0 ) {
     (void)SQLITE_MISUSE_BKPT;
-    if( zBuf && n>0 ) zBuf[0] = 0;
+    if( zBuf ) zBuf[0] = 0;
     return zBuf;
   }
 #endif
@@ -68947,6 +68969,9 @@ SQLITE_API void sqlite3_result_zeroblob(sqlite3_context *pCtx, int n){
 SQLITE_API void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){
   pCtx->isError = errCode;
   pCtx->fErrorOrAux = 1;
+#ifdef SQLITE_DEBUG
+  pCtx->pVdbe->rcApp = errCode;
+#endif
   if( pCtx->pOut->flags & MEM_Null ){
     sqlite3VdbeMemSetStr(pCtx->pOut, sqlite3ErrStr(errCode), -1, 
                          SQLITE_UTF8, SQLITE_STATIC);
@@ -69027,7 +69052,7 @@ static int sqlite3Step(Vdbe *p){
     ** or SQLITE_BUSY error.
     */
 #ifdef SQLITE_OMIT_AUTORESET
-    if( p->rc==SQLITE_BUSY || p->rc==SQLITE_LOCKED ){
+    if( (rc = p->rc&0xff)==SQLITE_BUSY || rc==SQLITE_LOCKED ){
       sqlite3_reset((sqlite3_stmt*)p);
     }else{
       return SQLITE_MISUSE_BKPT;
@@ -69073,6 +69098,9 @@ static int sqlite3Step(Vdbe *p){
     if( p->bIsReader ) db->nVdbeRead++;
     p->pc = 0;
   }
+#ifdef SQLITE_DEBUG
+  p->rcApp = SQLITE_OK;
+#endif
 #ifndef SQLITE_OMIT_EXPLAIN
   if( p->explain ){
     rc = sqlite3VdbeList(p);
@@ -69117,7 +69145,7 @@ end_of_step:
   assert( rc==SQLITE_ROW  || rc==SQLITE_DONE   || rc==SQLITE_ERROR 
        || rc==SQLITE_BUSY || rc==SQLITE_MISUSE
   );
-  assert( p->rc!=SQLITE_ROW && p->rc!=SQLITE_DONE );
+  assert( (p->rc!=SQLITE_ROW && p->rc!=SQLITE_DONE) || p->rc==p->rcApp );
   if( p->isPrepareV2 && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
     /* If this statement was prepared using sqlite3_prepare_v2(), and an
     ** error has occurred, then return the error code in p->rc to the
@@ -80825,9 +80853,10 @@ static int lookupName(
     testcase( pNC->ncFlags & NC_PartIdx );
     testcase( pNC->ncFlags & NC_IsCheck );
     if( (pNC->ncFlags & (NC_PartIdx|NC_IsCheck))!=0 ){
-      /* Silently ignore database qualifiers inside CHECK constraints and partial
-      ** indices.  Do not raise errors because that might break legacy and
-      ** because it does not hurt anything to just ignore the database name. */
+      /* Silently ignore database qualifiers inside CHECK constraints and
+      ** partial indices.  Do not raise errors because that might break
+      ** legacy and because it does not hurt anything to just ignore the
+      ** database name. */
       zDb = 0;
     }else{
       for(i=0; i<db->nDb; i++){
@@ -80898,7 +80927,8 @@ static int lookupName(
       if( pMatch ){
         pExpr->iTable = pMatch->iCursor;
         pExpr->pTab = pMatch->pTab;
-        assert( (pMatch->jointype & JT_RIGHT)==0 ); /* RIGHT JOIN not (yet) supported */
+        /* RIGHT JOIN not (yet) supported */
+        assert( (pMatch->jointype & JT_RIGHT)==0 );
         if( (pMatch->jointype & JT_LEFT)!=0 ){
           ExprSetProperty(pExpr, EP_CanBeNull);
         }
@@ -81219,7 +81249,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
       pExpr->affinity = SQLITE_AFF_INTEGER;
       break;
     }
-#endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) */
+#endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT)
+          && !defined(SQLITE_OMIT_SUBQUERY) */
 
     /* A lone identifier is the name of a column.
     */
@@ -81284,19 +81315,20 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
           if( n==2 ){
             pExpr->iTable = exprProbability(pList->a[1].pExpr);
             if( pExpr->iTable<0 ){
-              sqlite3ErrorMsg(pParse, "second argument to likelihood() must be a "
-                                      "constant between 0.0 and 1.0");
+              sqlite3ErrorMsg(pParse,
+                "second argument to likelihood() must be a "
+                "constant between 0.0 and 1.0");
               pNC->nErr++;
             }
           }else{
-            /* EVIDENCE-OF: R-61304-29449 The unlikely(X) function is equivalent to
-            ** likelihood(X, 0.0625).
-            ** EVIDENCE-OF: R-01283-11636 The unlikely(X) function is short-hand for
-            ** likelihood(X,0.0625).
-            ** EVIDENCE-OF: R-36850-34127 The likely(X) function is short-hand for
-            ** likelihood(X,0.9375).
-            ** EVIDENCE-OF: R-53436-40973 The likely(X) function is equivalent to
-            ** likelihood(X,0.9375). */
+            /* EVIDENCE-OF: R-61304-29449 The unlikely(X) function is
+            ** equivalent to likelihood(X, 0.0625).
+            ** EVIDENCE-OF: R-01283-11636 The unlikely(X) function is
+            ** short-hand for likelihood(X,0.0625).
+            ** EVIDENCE-OF: R-36850-34127 The likely(X) function is short-hand
+            ** for likelihood(X,0.9375).
+            ** EVIDENCE-OF: R-53436-40973 The likely(X) function is equivalent
+            ** to likelihood(X,0.9375). */
             /* TUNING: unlikely() probability is 0.0625.  likely() is 0.9375 */
             pExpr->iTable = pDef->zName[0]=='u' ? 8388608 : 125829120;
           }             
@@ -81313,7 +81345,9 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
           return WRC_Prune;
         }
 #endif
-        if( pDef->funcFlags & SQLITE_FUNC_CONSTANT ) ExprSetProperty(pExpr,EP_Constant);
+        if( pDef->funcFlags & SQLITE_FUNC_CONSTANT ){
+          ExprSetProperty(pExpr,EP_ConstFunc);
+        }
       }
       if( is_agg && (pNC->ncFlags & NC_AllowAgg)==0 ){
         sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId);
@@ -81624,7 +81658,8 @@ SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(
         resolveOutOfRangeError(pParse, zType, i+1, pEList->nExpr);
         return 1;
       }
-      resolveAlias(pParse, pEList, pItem->u.x.iOrderByCol-1, pItem->pExpr, zType,0);
+      resolveAlias(pParse, pEList, pItem->u.x.iOrderByCol-1, pItem->pExpr,
+                   zType,0);
     }
   }
   return 0;
@@ -82191,10 +82226,25 @@ SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
       break;
     }
     if( p->flags & EP_Collate ){
-      if( ALWAYS(p->pLeft) && (p->pLeft->flags & EP_Collate)!=0 ){
+      if( p->pLeft && (p->pLeft->flags & EP_Collate)!=0 ){
         p = p->pLeft;
       }else{
-        p = p->pRight;
+        Expr *pNext  = p->pRight;
+        /* The Expr.x union is never used at the same time as Expr.pRight */
+        assert( p->x.pList==0 || p->pRight==0 );
+        /* p->flags holds EP_Collate and p->pLeft->flags does not.  And
+        ** p->x.pSelect cannot.  So if p->x.pLeft exists, it must hold at
+        ** least one EP_Collate. Thus the following two ALWAYS. */
+        if( p->x.pList!=0 && ALWAYS(!ExprHasProperty(p, EP_xIsSelect)) ){
+          int i;
+          for(i=0; ALWAYS(i<p->x.pList->nExpr); i++){
+            if( ExprHasProperty(p->x.pList->a[i].pExpr, EP_Collate) ){
+              pNext = p->x.pList->a[i].pExpr;
+              break;
+            }
+          }
+        }
+        p = pNext;
       }
     }else{
       break;
@@ -82400,6 +82450,9 @@ static void heightOfSelect(Select *p, int *pnHeight){
 ** Expr.pSelect member has a height of 1. Any other expression
 ** has a height equal to the maximum height of any other 
 ** referenced Expr plus one.
+**
+** Also propagate EP_Propagate flags up from Expr.x.pList to Expr.flags,
+** if appropriate.
 */
 static void exprSetHeight(Expr *p){
   int nHeight = 0;
@@ -82407,8 +82460,9 @@ static void exprSetHeight(Expr *p){
   heightOfExpr(p->pRight, &nHeight);
   if( ExprHasProperty(p, EP_xIsSelect) ){
     heightOfSelect(p->x.pSelect, &nHeight);
-  }else{
+  }else if( p->x.pList ){
     heightOfExprList(p->x.pList, &nHeight);
+    p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList);
   }
   p->nHeight = nHeight + 1;
 }
@@ -82417,8 +82471,11 @@ static void exprSetHeight(Expr *p){
 ** Set the Expr.nHeight variable using the exprSetHeight() function. If
 ** the height is greater than the maximum allowed expression depth,
 ** leave an error in pParse.
+**
+** Also propagate all EP_Propagate flags from the Expr.x.pList into
+** Expr.flags. 
 */
-SQLITE_PRIVATE void sqlite3ExprSetHeight(Parse *pParse, Expr *p){
+SQLITE_PRIVATE void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){
   exprSetHeight(p);
   sqlite3ExprCheckHeight(pParse, p->nHeight);
 }
@@ -82432,8 +82489,17 @@ SQLITE_PRIVATE int sqlite3SelectExprHeight(Select *p){
   heightOfSelect(p, &nHeight);
   return nHeight;
 }
-#else
-  #define exprSetHeight(y)
+#else /* ABOVE:  Height enforcement enabled.  BELOW: Height enforcement off */
+/*
+** Propagate all EP_Propagate flags from the Expr.x.pList into
+** Expr.flags. 
+*/
+SQLITE_PRIVATE void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){
+  if( p && p->x.pList && !ExprHasProperty(p, EP_xIsSelect) ){
+    p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList);
+  }
+}
+#define exprSetHeight(y)
 #endif /* SQLITE_MAX_EXPR_DEPTH>0 */
 
 /*
@@ -82535,11 +82601,11 @@ SQLITE_PRIVATE void sqlite3ExprAttachSubtrees(
   }else{
     if( pRight ){
       pRoot->pRight = pRight;
-      pRoot->flags |= EP_Collate & pRight->flags;
+      pRoot->flags |= EP_Propagate & pRight->flags;
     }
     if( pLeft ){
       pRoot->pLeft = pLeft;
-      pRoot->flags |= EP_Collate & pLeft->flags;
+      pRoot->flags |= EP_Propagate & pLeft->flags;
     }
     exprSetHeight(pRoot);
   }
@@ -82639,7 +82705,7 @@ SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token *
   }
   pNew->x.pList = pList;
   assert( !ExprHasProperty(pNew, EP_xIsSelect) );
-  sqlite3ExprSetHeight(pParse, pNew);
+  sqlite3ExprSetHeightAndFlags(pParse, pNew);
   return pNew;
 }
 
@@ -83254,6 +83320,21 @@ SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){
   sqlite3DbFree(db, pList);
 }
 
+/*
+** Return the bitwise-OR of all Expr.flags fields in the given
+** ExprList.
+*/
+SQLITE_PRIVATE u32 sqlite3ExprListFlags(const ExprList *pList){
+  int i;
+  u32 m = 0;
+  if( pList ){
+    for(i=0; i<pList->nExpr; i++){
+       m |= pList->a[i].pExpr->flags;
+    }
+  }
+  return m;
+}
+
 /*
 ** These routines are Walker callbacks used to check expressions to
 ** see if they are "constant" for some definition of constant.  The
@@ -83294,7 +83375,7 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
     ** and either pWalker->eCode==4 or 5 or the function has the
     ** SQLITE_FUNC_CONST flag. */
     case TK_FUNCTION:
-      if( pWalker->eCode>=4 || ExprHasProperty(pExpr,EP_Constant) ){
+      if( pWalker->eCode>=4 || ExprHasProperty(pExpr,EP_ConstFunc) ){
         return WRC_Continue;
       }else{
         pWalker->eCode = 0;
@@ -90297,10 +90378,6 @@ SQLITE_PRIVATE Table *sqlite3FindTable(sqlite3 *db, const char *zName, const cha
   Table *p = 0;
   int i;
 
-#ifdef SQLITE_ENABLE_API_ARMOR
-  if( !sqlite3SafetyCheckOk(db) || zName==0 ) return 0;
-#endif
-
   /* All mutexes are required for schema access.  Make sure we hold them. */
   assert( zDatabase!=0 || sqlite3BtreeHoldsAllMutexes(db) );
 #if SQLITE_USER_AUTHENTICATION
@@ -94962,7 +95039,7 @@ SQLITE_PRIVATE Expr *sqlite3LimitWhere(
 
   pInClause->x.pSelect = pSelect;
   pInClause->flags |= EP_xIsSelect;
-  sqlite3ExprSetHeight(pParse, pInClause);
+  sqlite3ExprSetHeightAndFlags(pParse, pInClause);
   return pInClause;
 
   /* something went wrong. clean up anything allocated. */
@@ -108817,7 +108894,10 @@ static void substSelect(
 **
 **   (1)  The subquery and the outer query do not both use aggregates.
 **
-**   (2)  The subquery is not an aggregate or the outer query is not a join.
+**   (2)  The subquery is not an aggregate or (2a) the outer query is not a join
+**        and (2b) the outer query does not use subqueries other than the one
+**        FROM-clause subquery that is a candidate for flattening.  (2b is
+**        due to ticket [2f7170d73bf9abf80] from 2015-02-09.)
 **
 **   (3)  The subquery is not the right operand of a left outer join
 **        (Originally ticket #306.  Strengthened by ticket #3300)
@@ -108954,9 +109034,18 @@ static int flattenSubquery(
   iParent = pSubitem->iCursor;
   pSub = pSubitem->pSelect;
   assert( pSub!=0 );
-  if(p && (p->selFlags & SF_NOFlattening)) return 0;
-  if( isAgg && subqueryIsAgg ) return 0;                 /* Restriction (1)  */
-  if( subqueryIsAgg && pSrc->nSrc>1 ) return 0;          /* Restriction (2)  */
+  if(p->selFlags & SF_NOFlattening) return 0;
+  if( subqueryIsAgg ){
+    if( isAgg ) return 0;                                /* Restriction (1)   */
+    if( pSrc->nSrc>1 ) return 0;                         /* Restriction (2a)  */
+    if( (p->pWhere && ExprHasProperty(p->pWhere,EP_Subquery))
+     || (sqlite3ExprListFlags(p->pEList) & EP_Subquery)!=0
+     || (sqlite3ExprListFlags(p->pOrderBy) & EP_Subquery)!=0
+    ){
+      return 0;                                          /* Restriction (2b)  */
+    }
+  }
+    
   pSubSrc = pSub->pSrc;
   assert( pSubSrc );
   /* Prior to version 3.1.2, when LIMIT and OFFSET had to be simple constants,
@@ -110376,6 +110465,13 @@ SQLITE_PRIVATE int sqlite3Select(
   }
   isAgg = (p->selFlags & SF_Aggregate)!=0;
   assert( pEList!=0 );
+#if SELECTTRACE_ENABLED
+  if( sqlite3SelectTrace & 0x100 ){
+    SELECTTRACE(0x100,pParse,p, ("after name resolution:\n"));
+    sqlite3TreeViewSelect(0, p, 0);
+  }
+#endif
+
 
   /* Begin generating code.
   */
@@ -111121,9 +111217,9 @@ select_end:
 SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
   int n = 0;
   pView = sqlite3TreeViewPush(pView, moreToFollow);
-  sqlite3TreeViewLine(pView, "SELECT%s%s",
+  sqlite3TreeViewLine(pView, "SELECT%s%s (0x%p)",
     ((p->selFlags & SF_Distinct) ? " DISTINCT" : ""),
-    ((p->selFlags & SF_Aggregate) ? " agg_flag" : "")
+    ((p->selFlags & SF_Aggregate) ? " agg_flag" : ""), p
   );
   if( p->pSrc && p->pSrc->nSrc ) n++;
   if( p->pWhere ) n++;
@@ -114390,7 +114486,9 @@ SQLITE_API int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
   char *zErr = 0;
 
 #ifdef SQLITE_ENABLE_API_ARMOR
-  if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
+  if( !sqlite3SafetyCheckOk(db) || zCreateTable==0 ){
+    return SQLITE_MISUSE_BKPT;
+  }
 #endif
   sqlite3_mutex_enter(db->mutex);
   if( !db->pVtabCtx || !(pTab = db->pVtabCtx->pTab) ){
@@ -124905,7 +125003,7 @@ static void yy_reduce(
       yygotominor.yy94.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy94.pExpr, 0, 0);
       if( yygotominor.yy94.pExpr ){
         yygotominor.yy94.pExpr->x.pList = yymsp[-1].minor.yy298;
-        sqlite3ExprSetHeight(pParse, yygotominor.yy94.pExpr);
+        sqlite3ExprSetHeightAndFlags(pParse, yygotominor.yy94.pExpr);
       }else{
         sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy298);
       }
@@ -124920,8 +125018,8 @@ static void yy_reduce(
     yygotominor.yy94.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0);
     if( yygotominor.yy94.pExpr ){
       yygotominor.yy94.pExpr->x.pSelect = yymsp[-1].minor.yy27;
-      ExprSetProperty(yygotominor.yy94.pExpr, EP_xIsSelect);
-      sqlite3ExprSetHeight(pParse, yygotominor.yy94.pExpr);
+      ExprSetProperty(yygotominor.yy94.pExpr, EP_xIsSelect|EP_Subquery);
+      sqlite3ExprSetHeightAndFlags(pParse, yygotominor.yy94.pExpr);
     }else{
       sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy27);
     }
@@ -124934,8 +125032,8 @@ static void yy_reduce(
     yygotominor.yy94.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy94.pExpr, 0, 0);
     if( yygotominor.yy94.pExpr ){
       yygotominor.yy94.pExpr->x.pSelect = yymsp[-1].minor.yy27;
-      ExprSetProperty(yygotominor.yy94.pExpr, EP_xIsSelect);
-      sqlite3ExprSetHeight(pParse, yygotominor.yy94.pExpr);
+      ExprSetProperty(yygotominor.yy94.pExpr, EP_xIsSelect|EP_Subquery);
+      sqlite3ExprSetHeightAndFlags(pParse, yygotominor.yy94.pExpr);
     }else{
       sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy27);
     }
@@ -124950,8 +125048,8 @@ static void yy_reduce(
     yygotominor.yy94.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-3].minor.yy94.pExpr, 0, 0);
     if( yygotominor.yy94.pExpr ){
       yygotominor.yy94.pExpr->x.pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0);
-      ExprSetProperty(yygotominor.yy94.pExpr, EP_xIsSelect);
-      sqlite3ExprSetHeight(pParse, yygotominor.yy94.pExpr);
+      ExprSetProperty(yygotominor.yy94.pExpr, EP_xIsSelect|EP_Subquery);
+      sqlite3ExprSetHeightAndFlags(pParse, yygotominor.yy94.pExpr);
     }else{
       sqlite3SrcListDelete(pParse->db, pSrc);
     }
@@ -124965,8 +125063,8 @@ static void yy_reduce(
     Expr *p = yygotominor.yy94.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0);
     if( p ){
       p->x.pSelect = yymsp[-1].minor.yy27;
-      ExprSetProperty(p, EP_xIsSelect);
-      sqlite3ExprSetHeight(pParse, p);
+      ExprSetProperty(p, EP_xIsSelect|EP_Subquery);
+      sqlite3ExprSetHeightAndFlags(pParse, p);
     }else{
       sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy27);
     }
@@ -124979,7 +125077,7 @@ static void yy_reduce(
   yygotominor.yy94.pExpr = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy326, 0, 0);
   if( yygotominor.yy94.pExpr ){
     yygotominor.yy94.pExpr->x.pList = yymsp[-1].minor.yy326 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy298,yymsp[-1].minor.yy326) : yymsp[-2].minor.yy298;
-    sqlite3ExprSetHeight(pParse, yygotominor.yy94.pExpr);
+    sqlite3ExprSetHeightAndFlags(pParse, yygotominor.yy94.pExpr);
   }else{
     sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy298);
     sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy326);
@@ -126222,10 +126320,7 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr
   sqlite3 *db = pParse->db;       /* The database connection */
   int mxSqlLen;                   /* Max length of an SQL string */
 
-
-#ifdef SQLITE_ENABLE_API_ARMOR
-  if( zSql==0 || pzErrMsg==0 ) return SQLITE_MISUSE_BKPT;
-#endif
+  assert( zSql!=0 );
   mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
   if( db->nVdbeActive==0 ){
     db->u1.isInterrupted = 0;
@@ -128251,7 +128346,7 @@ SQLITE_API int sqlite3_busy_handler(
   void *pArg
 ){
 #ifdef SQLITE_ENABLE_API_ARMOR
-  if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE;
+  if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
 #endif
   sqlite3_mutex_enter(db->mutex);
   db->busyHandler.xFunc = xBusy;
@@ -130018,13 +130113,19 @@ SQLITE_API int sqlite3_table_column_metadata(
   Table *pTab = 0;
   Column *pCol = 0;
   int iCol = 0;
-
   char const *zDataType = 0;
   char const *zCollSeq = 0;
   int notnull = 0;
   int primarykey = 0;
   int autoinc = 0;
 
+
+#ifdef SQLITE_ENABLE_API_ARMOR
+  if( !sqlite3SafetyCheckOk(db) || zTableName==0 ){
+    return SQLITE_MISUSE_BKPT;
+  }
+#endif
+
   /* Ensure the database schema has been loaded */
   sqlite3_mutex_enter(db->mutex);
   sqlite3BtreeEnterAll(db);

+ 1 - 1
SquiLu-ext/sqlite3.h

@@ -109,7 +109,7 @@ extern "C" {
 */
 #define SQLITE_VERSION        "3.8.8"
 #define SQLITE_VERSION_NUMBER 3008008
-#define SQLITE_SOURCE_ID      "2015-02-07 15:16:35 5df02f50f8348dfde4fc15126abc7b7ef7803e69"
+#define SQLITE_SOURCE_ID      "2015-02-13 16:36:14 823ad40ccb5b51aaa0d5a48da63b465df9d0649a"
 
 /*
 ** CAPI3REF: Run-Time Library Version Numbers

+ 8 - 8
SquiLu/Makefile-SquiLu

@@ -1,27 +1,27 @@
 
 #INC =  -Iinclude -Isqstdlib -I../myaxtls -I../discount -I/usr/include/postgresql -I/usr/lib/jvm/default-java/include -I/usr/lib/llvm-3.1/include -I../SquiLu-ext/threadObject -I..
 #INC =  -Iinclude -Isqstdlib -I../myaxtls -I../discount -I..
-INC =  -Iinclude -Isqstdlib -I../discount -I../gumbo -I..
-#CFLAGS =  -Wall -fno-strict-aliasing -DSQ_JIT_LLVM44=1 -D_DEBUG_DUMP33=1 -DWITH_DAD_EXTRAS=1 -DSQ_SUBLATIN=1 -DNEED_SUBLATIN_C2=1 -DSQUSEDOUBLE=1 -DSQUSEDECIMAL642=1 -DNO_EXCEPTION_KEY_NOT_FOUND0=1 -D_SQ642=1 -DNO_GARBAGE_COLLECTOR00=1 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_DEFAULT_AUTOVACUUM=1 -DSQLITE_DEFAULT_FOREIGN_KEYS=1 -DSQLITE_ENABLE_COLUMN_METADATA=1 -DSQLITE_ENABLE_EXTENSION_FUNCTIONS=1 -DSQLITE_ENABLE_FTS3=1 -DSQLITE_ENABLE_FTS3_PARENTHESIS=1 -DSQLITE_ENABLE_UNLOCK_NOTIFY=1 -DSQLITE_ENABLE_RTREE=1 -DSQLITE_ENABLE_STAT3=1 -DSQLITE_HAS_CODEC=1 -DSQLITE_OMIT_TCL_VARIABLE=1 -DSQLITE_USE_URI=1 -DSQLITE_SOUNDEX=1 -DNO_POPEN=1 -DNO_SSL_DL=1 -DHAVE_STDINT=1 -DUSE_AXTLS=1 -DUSE_AXTLS_ON_MEMORY=1 -D_FILE_OFFSET_BITS=64 -DSSL_STATIC_LIBRARY=1 -DPDF_USING_ZLIB=1 -DRS232_STATIC=1
+INC =  -Iinclude -Isqstdlib -I../myaxtls -I../discount -I../gumbo -I.. -I../minizip
+#CFLAGS =  -Wall -fno-strict-aliasing -DSQ_JIT_LLVM44=1 -D_DEBUG_DUMP33=1 -DWITH_DAD_EXTRAS=1 -DSQ_SUBLATIN=1 -DNEED_SUBLATIN_C2=1 -DSQUSEDOUBLE=1 -DSQUSEDECIMAL64=1 -DNO_EXCEPTION_KEY_NOT_FOUND0=1 -D_SQ642=1 -DNO_GARBAGE_COLLECTOR00=1 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_DEFAULT_AUTOVACUUM=1 -DSQLITE_DEFAULT_FOREIGN_KEYS=1 -DSQLITE_ENABLE_COLUMN_METADATA=1 -DSQLITE_ENABLE_EXTENSION_FUNCTIONS=1 -DSQLITE_ENABLE_FTS3=1 -DSQLITE_ENABLE_FTS3_PARENTHESIS=1 -DSQLITE_ENABLE_UNLOCK_NOTIFY=1 -DSQLITE_ENABLE_RTREE=1 -DSQLITE_ENABLE_STAT3=1 -DSQLITE_HAS_CODEC=1 -DSQLITE_OMIT_TCL_VARIABLE=1 -DSQLITE_USE_URI=1 -DSQLITE_SOUNDEX=1 -DNO_POPEN=1 -DNO_SSL_DL=1 -DHAVE_STDINT=1 -DUSE_AXTLS=1 -DUSE_AXTLS_ON_MEMORY=1 -D_FILE_OFFSET_BITS=64 -DSSL_STATIC_LIBRARY=1 -DPDF_USING_ZLIB=1 -DRS232_STATIC=1
 CFLAGS = $(INC) -O3 -Wall -fno-strict-aliasing -DNDEBUG -DWITH_DAD_EXTRAS=1 -DSQ_SUBLATIN=1 \
-	-DSQUSEDOUBLE=1  -D_SQ642=1 \
+	-DSQUSEDOUBLE=1  -D_SQ64=1 -DCONFIG_64 \
 	-DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_DEFAULT_AUTOVACUUM=1 \
 	-DSQLITE_DEFAULT_FOREIGN_KEYS=1 -DSQLITE_ENABLE_COLUMN_METADATA=1 \
 	-DSQLITE_ENABLE_EXTENSION_FUNCTIONS=1 -DSQLITE_ENABLE_FTS3=1 \
 	-DSQLITE_ENABLE_FTS3_PARENTHESIS=1 -DSQLITE_ENABLE_UNLOCK_NOTIFY=1 \
 	-DSQLITE_ENABLE_RTREE=1 -DSQLITE_ENABLE_STAT3=1 -DSQLITE_HAS_CODEC=1 \
 	-DSQLITE_OMIT_TCL_VARIABLE=1 -DSQLITE_USE_URI=1 -DSQLITE_SOUNDEX=1 \
-	-DNO_POPEN=1 -DNO_SSL_DL2=1 -DHAVE_STDINT=1 -DUSE_AXTLS2=1 -DNO_SSL2=1\
+	-DNO_POPEN=1 -DNO_SSL_DL=1 -DHAVE_STDINT=1 -DUSE_AXTLS=1 -DNO_SSL=1\
 	-DUSE_AXTLS_ON_MEMORY=1 -D_FILE_OFFSET_BITS=64 \
 	-DSSL_STATIC_LIBRARY=1 -DPDF_USING_ZLIB=1 -DRS232_STATIC=1 \
 	-DUSE_SIGNAL_HANDLER=1
 
 RESINC = 
 #LIBDIR =  -Llib -L../myaxtls -L../mpdecimal -L../discount
-LIBDIR =  -Llib -L../mpdecimal -L../discount -L../gumbo
+LIBDIR =  -Llib -L../myaxtls -L../mpdecimal -L../discount -L../gumbo -L../minizip
 LIB =  -lm
 #LDFLAGS =  -lpthread -lrt -ldl -laxtls -lmpdecimal -ldiscount -lz
-LDFLAGS =  -lpthread -lrt -ldl -lmpdecimal -ldiscount -lgumbo -lz
+LDFLAGS =  -lpthread -lrt -ldl -laxtls -lmpdecimal -ldiscount -lgumbo -lminizip -lz
 CC = gcc
 CXX = g++
 
@@ -32,12 +32,12 @@ SOURCES=  sq/sq.c  sqstdlib/sqstdaux.cpp  sqstdlib/sqstdblob.cpp  sqstdlib/sqstd
 	../SquiLu-ext/mongoose.c  ../SquiLu-ext/pdf-font.cpp  ../SquiLu-ext/sq_axtls.c  \
 	../SquiLu-ext/sq_base64.cpp  ../SquiLu-ext/sq_decimal.cpp  \
 	../SquiLu-ext/sq_fpdf.cpp  ../SquiLu-ext/sq_fs.c  \
-	../SquiLu-ext/sqlite3.c  ../SquiLu-ext/sq_markdown.cpp  ../SquiLu-ext/sq_mix.cpp  \
+	../SquiLu-ext/sqlite3.c  ../SquiLu-ext/sq_markdown.cpp  \
 	../SquiLu-ext/sq_mongoose.cpp  ../SquiLu-ext/sqratimport.cpp  \
 	../SquiLu-ext/sq_rs232.c  ../SquiLu-ext/sq_slave_vm.cpp  \
 	../SquiLu-ext/sq_socket.cpp  ../SquiLu-ext/sq_sqlite3.cpp  \
 	../SquiLu-ext/sq_tinyxml2.cpp  ../SquiLu-ext/sq_zlib.cpp  \
-	../SquiLu-ext/tinyxml2.cpp ../SquiLu-ext/sq_gumbo.cpp  \
+	../SquiLu-ext/tinyxml2.cpp ../SquiLu-ext/sq_gumbo.cpp  ../SquiLu-ext/sq_mix.c \
 	squirrel/lua-regex.c  squirrel/sqdebug.cpp  squirrel/sqapi.cpp  \
 	squirrel/sqbaselib.cpp  squirrel/sqclass.cpp  squirrel/sqcompiler.cpp  \
 	squirrel/sqfuncstate.cpp  squirrel/sqlexer.cpp  squirrel/sqmem.cpp  \

+ 1 - 1
SquiLu/sq/sq.c

@@ -588,7 +588,7 @@ int main(int argc, char* argv[])
 
 	sqext_register_sq_slave_vm(v);
 	//sqext_register_ThreadObjects(v);
-	sqext_register_dad_utils(v);
+	//sqext_register_dad_utils(v);
 	//sqext_register_sys(v);
 
 #ifdef WITH_FULL_DAD_EXTRAS

+ 33 - 40
libharu/libharu.cbp

@@ -3,19 +3,19 @@
 	<FileVersion major="1" minor="6" />
 	<Project>
 		<Option title="libharu" />
-		<Option compiler="gnu_gcc_compiler_static" />
+		<Option compiler="gcc" />
 		<MakeCommands>
-			<Build command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/src/Makefile hpdfs" />
-			<CompileFile command='C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/src/Makefile &quot;$file&quot;' />
-			<Clean command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/src/Makefile clean" />
-			<DistClean command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/src/Makefile clean" />
+			<Build command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile all" />
+			<CompileFile command='C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile &quot;$file&quot;' />
+			<Clean command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile clean" />
+			<DistClean command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile clean" />
 			<AskRebuildNeeded command="$make -q -f $makefile $target" />
-			<SilentBuild command="$make -s -f $makefile $target" />
+			<SilentBuild command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile all &gt; $(CMD_NULL)" />
 		</MakeCommands>
 		<Build>
 			<Target title="all">
 				<Option type="4" />
-				<Option compiler="gnu_gcc_compiler_static" />
+				<Option compiler="gcc" />
 				<Compiler>
 					<Add directory="include" />
 				</Compiler>
@@ -25,103 +25,103 @@
 					<Clean command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile clean" />
 					<DistClean command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile clean" />
 					<AskRebuildNeeded command="$make -q -f $makefile $target" />
-					<SilentBuild command="$make -s -f $makefile $target" />
+					<SilentBuild command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile all &gt; $(CMD_NULL)" />
 				</MakeCommands>
 			</Target>
 			<Target title="edit_cache">
 				<Option type="4" />
-				<Option compiler="gnu_gcc_compiler_static" />
+				<Option compiler="gcc" />
 				<MakeCommands>
 					<Build command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile edit_cache" />
 					<CompileFile command='C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile &quot;$file&quot;' />
 					<Clean command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile clean" />
 					<DistClean command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile clean" />
 					<AskRebuildNeeded command="$make -q -f $makefile $target" />
-					<SilentBuild command="$make -s -f $makefile $target" />
+					<SilentBuild command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile edit_cache &gt; $(CMD_NULL)" />
 				</MakeCommands>
 			</Target>
 			<Target title="install">
 				<Option type="4" />
-				<Option compiler="gnu_gcc_compiler_static" />
+				<Option compiler="gcc" />
 				<MakeCommands>
 					<Build command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile install" />
 					<CompileFile command='C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile &quot;$file&quot;' />
 					<Clean command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile clean" />
 					<DistClean command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile clean" />
 					<AskRebuildNeeded command="$make -q -f $makefile $target" />
-					<SilentBuild command="$make -s -f $makefile $target" />
+					<SilentBuild command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile install &gt; $(CMD_NULL)" />
 				</MakeCommands>
 			</Target>
 			<Target title="install/local">
 				<Option type="4" />
-				<Option compiler="gnu_gcc_compiler_static" />
+				<Option compiler="gcc" />
 				<MakeCommands>
 					<Build command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile install/local" />
 					<CompileFile command='C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile &quot;$file&quot;' />
 					<Clean command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile clean" />
 					<DistClean command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile clean" />
 					<AskRebuildNeeded command="$make -q -f $makefile $target" />
-					<SilentBuild command="$make -s -f $makefile $target" />
+					<SilentBuild command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile install/local &gt; $(CMD_NULL)" />
 				</MakeCommands>
 			</Target>
 			<Target title="install/strip">
 				<Option type="4" />
-				<Option compiler="gnu_gcc_compiler_static" />
+				<Option compiler="gcc" />
 				<MakeCommands>
 					<Build command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile install/strip" />
 					<CompileFile command='C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile &quot;$file&quot;' />
 					<Clean command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile clean" />
 					<DistClean command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile clean" />
 					<AskRebuildNeeded command="$make -q -f $makefile $target" />
-					<SilentBuild command="$make -s -f $makefile $target" />
+					<SilentBuild command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile install/strip &gt; $(CMD_NULL)" />
 				</MakeCommands>
 			</Target>
 			<Target title="list_install_components">
 				<Option type="4" />
-				<Option compiler="gnu_gcc_compiler_static" />
+				<Option compiler="gcc" />
 				<MakeCommands>
 					<Build command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile list_install_components" />
 					<CompileFile command='C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile &quot;$file&quot;' />
 					<Clean command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile clean" />
 					<DistClean command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile clean" />
 					<AskRebuildNeeded command="$make -q -f $makefile $target" />
-					<SilentBuild command="$make -s -f $makefile $target" />
+					<SilentBuild command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile list_install_components &gt; $(CMD_NULL)" />
 				</MakeCommands>
 			</Target>
 			<Target title="package">
 				<Option type="4" />
-				<Option compiler="gnu_gcc_compiler_static" />
+				<Option compiler="gcc" />
 				<MakeCommands>
 					<Build command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile package" />
 					<CompileFile command='C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile &quot;$file&quot;' />
 					<Clean command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile clean" />
 					<DistClean command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile clean" />
 					<AskRebuildNeeded command="$make -q -f $makefile $target" />
-					<SilentBuild command="$make -s -f $makefile $target" />
+					<SilentBuild command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile package &gt; $(CMD_NULL)" />
 				</MakeCommands>
 			</Target>
 			<Target title="package_source">
 				<Option type="4" />
-				<Option compiler="gnu_gcc_compiler_static" />
+				<Option compiler="gcc" />
 				<MakeCommands>
 					<Build command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile package_source" />
 					<CompileFile command='C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile &quot;$file&quot;' />
 					<Clean command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile clean" />
 					<DistClean command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile clean" />
 					<AskRebuildNeeded command="$make -q -f $makefile $target" />
-					<SilentBuild command="$make -s -f $makefile $target" />
+					<SilentBuild command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile package_source &gt; $(CMD_NULL)" />
 				</MakeCommands>
 			</Target>
 			<Target title="rebuild_cache">
 				<Option type="4" />
-				<Option compiler="gnu_gcc_compiler_static" />
+				<Option compiler="gcc" />
 				<MakeCommands>
 					<Build command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile rebuild_cache" />
 					<CompileFile command='C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile &quot;$file&quot;' />
 					<Clean command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile clean" />
 					<DistClean command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile clean" />
 					<AskRebuildNeeded command="$make -q -f $makefile $target" />
-					<SilentBuild command="$make -s -f $makefile $target" />
+					<SilentBuild command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/Makefile rebuild_cache &gt; $(CMD_NULL)" />
 				</MakeCommands>
 			</Target>
 			<Target title="hpdf">
@@ -129,7 +129,7 @@
 				<Option working_dir="G:/tmp/c/libharu-git/libharu/src" />
 				<Option object_output="./" />
 				<Option type="3" />
-				<Option compiler="gnu_gcc_compiler_static" />
+				<Option compiler="gcc" />
 				<Compiler>
 					<Add directory="C:/Program Files/Gtk+/include" />
 					<Add directory="G:/tmp/c/libharu-git/libharu/include" />
@@ -140,7 +140,7 @@
 					<Clean command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/src/Makefile clean" />
 					<DistClean command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/src/Makefile clean" />
 					<AskRebuildNeeded command="$make -q -f $makefile $target" />
-					<SilentBuild command="$make -s -f $makefile $target" />
+					<SilentBuild command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/src/Makefile hpdf &gt; $(CMD_NULL)" />
 				</MakeCommands>
 			</Target>
 			<Target title="hpdf/fast">
@@ -148,7 +148,7 @@
 				<Option working_dir="G:/tmp/c/libharu-git/libharu/src" />
 				<Option object_output="./" />
 				<Option type="3" />
-				<Option compiler="gnu_gcc_compiler_static" />
+				<Option compiler="gcc" />
 				<Compiler>
 					<Add directory="C:/Program Files/Gtk+/include" />
 					<Add directory="G:/tmp/c/libharu-git/libharu/include" />
@@ -159,7 +159,7 @@
 					<Clean command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/src/Makefile clean" />
 					<DistClean command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/src/Makefile clean" />
 					<AskRebuildNeeded command="$make -q -f $makefile $target" />
-					<SilentBuild command="$make -s -f $makefile $target" />
+					<SilentBuild command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/src/Makefile hpdf/fast &gt; $(CMD_NULL)" />
 				</MakeCommands>
 			</Target>
 			<Target title="hpdfs">
@@ -191,7 +191,7 @@
 				<Option working_dir="" />
 				<Option object_output="./" />
 				<Option type="2" />
-				<Option compiler="gnu_gcc_compiler_static" />
+				<Option compiler="gcc" />
 				<Compiler>
 					<Add directory="C:/Program Files/Gtk+/include" />
 					<Add directory="G:/tmp/c/libharu-git/libharu/include" />
@@ -202,7 +202,7 @@
 					<Clean command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/src/Makefile clean" />
 					<DistClean command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/src/Makefile clean" />
 					<AskRebuildNeeded command="$make -q -f $makefile $target" />
-					<SilentBuild command="$make -s -f $makefile $target" />
+					<SilentBuild command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/src/Makefile hpdfs/fast &gt; $(CMD_NULL)" />
 				</MakeCommands>
 			</Target>
 			<Target title="hpdfs MinGW-CROSS">
@@ -210,7 +210,7 @@
 				<Option working_dir="" />
 				<Option object_output="./" />
 				<Option type="2" />
-				<Option compiler="mingw_gnu_gcc_compiler" />
+				<Option compiler="gcc" />
 				<Compiler>
 					<Add option="-O2" />
 					<Add option="-Wall" />
@@ -226,20 +226,13 @@
 					<Clean command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/src/Makefile clean" />
 					<DistClean command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/src/Makefile clean" />
 					<AskRebuildNeeded command="$make -q -f $makefile $target" />
-					<SilentBuild command="$make -s -f $makefile $target" />
+					<SilentBuild command="C:/MinGW32/bin/mingw32-make.exe -f G:/tmp/c/libharu-git/libharu/src/Makefile hpdfs &gt; $(CMD_NULL)" />
 				</MakeCommands>
 			</Target>
 		</Build>
 		<Compiler>
-			<Add option="-O2" />
-			<Add option="-Wall" />
-			<Add directory="../fltk/png" />
-			<Add directory="../fltk/jpeg" />
-			<Add directory="../fltk/zlib" />
+			<Add directory="include" />
 		</Compiler>
-		<Linker>
-			<Add option="-s" />
-		</Linker>
 		<Unit filename="src/hpdf_3dmeasure.c">
 			<Option compilerVar="CC" />
 		</Unit>

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 167 - 0
libharu/libharu.cbp.mak


+ 110 - 0
minizip/minizip.cbp.mak

@@ -0,0 +1,110 @@
+#------------------------------------------------------------------------------#
+# This makefile was generated by 'cbp2make' tool rev.135                       #
+#------------------------------------------------------------------------------#
+
+
+WORKDIR = `pwd`
+
+CC = gcc
+CXX = g++
+AR = ar
+LD = g++
+WINDRES = windres
+
+INC = 
+CFLAGS =  -DNOCRYPT=1
+RESINC = 
+LIBDIR = 
+LIB = 
+LDFLAGS = 
+
+INC_DEBUG =  $(INC)
+CFLAGS_DEBUG =  $(CFLAGS) -Wall -g
+RESINC_DEBUG =  $(RESINC)
+RCFLAGS_DEBUG =  $(RCFLAGS)
+LIBDIR_DEBUG =  $(LIBDIR)
+LIB_DEBUG = $(LIB)
+LDFLAGS_DEBUG =  $(LDFLAGS)
+OBJDIR_DEBUG = obj/Debug
+DEP_DEBUG = 
+OUT_DEBUG = libminizip.a
+
+INC_RELEASE =  $(INC)
+CFLAGS_RELEASE =  $(CFLAGS) -Wall -O2
+RESINC_RELEASE =  $(RESINC)
+RCFLAGS_RELEASE =  $(RCFLAGS)
+LIBDIR_RELEASE =  $(LIBDIR)
+LIB_RELEASE = $(LIB)
+LDFLAGS_RELEASE =  $(LDFLAGS) -s
+OBJDIR_RELEASE = obj/Release
+DEP_RELEASE = 
+OUT_RELEASE = libminizip.a
+
+OBJ_DEBUG = $(OBJDIR_DEBUG)/ioapi.o $(OBJDIR_DEBUG)/iowin32.o $(OBJDIR_DEBUG)/mztools.o $(OBJDIR_DEBUG)/unzip.o $(OBJDIR_DEBUG)/zip.o
+
+OBJ_RELEASE = $(OBJDIR_RELEASE)/ioapi.o $(OBJDIR_RELEASE)/iowin32.o $(OBJDIR_RELEASE)/mztools.o $(OBJDIR_RELEASE)/unzip.o $(OBJDIR_RELEASE)/zip.o
+
+all: debug release
+
+clean: clean_debug clean_release
+
+before_debug: 
+	test -d $(OBJDIR_DEBUG) || mkdir -p $(OBJDIR_DEBUG)
+
+after_debug: 
+
+debug: before_debug out_debug after_debug
+
+out_debug: $(OBJ_DEBUG) $(DEP_DEBUG)
+	$(AR) rcs $(OUT_DEBUG) $(OBJ_DEBUG)
+
+$(OBJDIR_DEBUG)/ioapi.o: ioapi.c
+	$(CC) $(CFLAGS_DEBUG) $(INC_DEBUG) -c ioapi.c -o $(OBJDIR_DEBUG)/ioapi.o
+
+$(OBJDIR_DEBUG)/iowin32.o: iowin32.c
+	$(CC) $(CFLAGS_DEBUG) $(INC_DEBUG) -c iowin32.c -o $(OBJDIR_DEBUG)/iowin32.o
+
+$(OBJDIR_DEBUG)/mztools.o: mztools.c
+	$(CC) $(CFLAGS_DEBUG) $(INC_DEBUG) -c mztools.c -o $(OBJDIR_DEBUG)/mztools.o
+
+$(OBJDIR_DEBUG)/unzip.o: unzip.c
+	$(CC) $(CFLAGS_DEBUG) $(INC_DEBUG) -c unzip.c -o $(OBJDIR_DEBUG)/unzip.o
+
+$(OBJDIR_DEBUG)/zip.o: zip.c
+	$(CC) $(CFLAGS_DEBUG) $(INC_DEBUG) -c zip.c -o $(OBJDIR_DEBUG)/zip.o
+
+clean_debug: 
+	rm -f $(OBJ_DEBUG) $(OUT_DEBUG)
+	rm -rf $(OBJDIR_DEBUG)
+
+before_release: 
+	test -d $(OBJDIR_RELEASE) || mkdir -p $(OBJDIR_RELEASE)
+
+after_release: 
+
+release: before_release out_release after_release
+
+out_release: $(OBJ_RELEASE) $(DEP_RELEASE)
+	$(AR) rcs $(OUT_RELEASE) $(OBJ_RELEASE)
+
+$(OBJDIR_RELEASE)/ioapi.o: ioapi.c
+	$(CC) $(CFLAGS_RELEASE) $(INC_RELEASE) -c ioapi.c -o $(OBJDIR_RELEASE)/ioapi.o
+
+$(OBJDIR_RELEASE)/iowin32.o: iowin32.c
+	$(CC) $(CFLAGS_RELEASE) $(INC_RELEASE) -c iowin32.c -o $(OBJDIR_RELEASE)/iowin32.o
+
+$(OBJDIR_RELEASE)/mztools.o: mztools.c
+	$(CC) $(CFLAGS_RELEASE) $(INC_RELEASE) -c mztools.c -o $(OBJDIR_RELEASE)/mztools.o
+
+$(OBJDIR_RELEASE)/unzip.o: unzip.c
+	$(CC) $(CFLAGS_RELEASE) $(INC_RELEASE) -c unzip.c -o $(OBJDIR_RELEASE)/unzip.o
+
+$(OBJDIR_RELEASE)/zip.o: zip.c
+	$(CC) $(CFLAGS_RELEASE) $(INC_RELEASE) -c zip.c -o $(OBJDIR_RELEASE)/zip.o
+
+clean_release: 
+	rm -f $(OBJ_RELEASE) $(OUT_RELEASE)
+	rm -rf $(OBJDIR_RELEASE)
+
+.PHONY: before_debug after_debug clean_debug before_release after_release clean_release
+

+ 87 - 0
mpdecimal/README.txt

@@ -0,0 +1,87 @@
+
+
+libmpdec
+========
+
+libmpdec is a fast C/C++ library for correctly-rounded arbitrary precision
+decimal floating point arithmetic. It is a complete implementation of
+Mike Cowlishaw/IBM's General Decimal Arithmetic Specification.
+
+
+  Core files for small and medium precision arithmetic
+  ----------------------------------------------------
+
+    basearith.{c,h}  ->  Core arithmetic in base 10**9 or 10**19.
+    bits.h           ->  Portable detection of least/most significant one-bit.
+    constants.{c,h}  ->  Constants that are used in multiple files.
+    context.c        ->  Context functions.
+    io.{c,h}         ->  Conversions between mpd_t and ASCII strings,
+                         mpd_t formatting (allows UTF-8 fill character).
+    memory.{c,h}     ->  Allocation handlers with overflow detection
+                         and functions for switching between static
+                         and dynamic mpd_t.
+    mpdecimal.{c,h}  ->  All (quiet) functions of the specification.
+    typearith.h      ->  Fast primitives for double word multiplication,
+                         division etc.
+
+    Visual Studio only:
+    ~~~~~~~~~~~~~~~~~~~
+      vccompat.h    ->  snprintf <==> sprintf_s and similar things.
+      vcstdint.h    ->  stdint.h (included in VS 2010 but not in VS 2008).
+      vcdiv64.asm   ->  Double word division used in typearith.h. VS 2008 does
+                        not allow inline asm for x64. Also, it does not provide
+                        an intrinsic for double word division.
+
+  Files for bignum arithmetic:
+  ----------------------------
+
+    The following files implement the Fast Number Theoretic Transform
+    used for multiplying coefficients with more than 1024 words (see
+    mpdecimal.c: _mpd_fntmul()).
+
+      umodarith.h        ->  Fast low level routines for unsigned modular arithmetic.
+      numbertheory.{c,h} ->  Routines for setting up the Number Theoretic Transform.
+      difradix2.{c,h}    ->  Decimation in frequency transform, used as the
+                             "base case" by the following three files:
+
+        fnt.{c,h}        ->  Transform arrays up to 4096 words.
+        sixstep.{c,h}    ->  Transform larger arrays of length 2**n.
+        fourstep.{c,h}   ->  Transform larger arrays of length 3 * 2**n.
+
+      convolute.{c,h}    ->  Fast convolution using one of the three transform
+                             functions.
+      transpose.{c,h}    ->  Transpositions needed for the sixstep algorithm.
+      crt.{c,h}          ->  Chinese Remainder Theorem: use information from three
+                             transforms modulo three different primes to get the
+                             final result.
+
+
+Pointers to literature, proofs and more
+=======================================
+
+  literature/
+  -----------
+
+    REFERENCES.txt  ->  List of relevant papers.
+    bignum.txt      ->  Explanation of the Fast Number Theoretic Transform (FNT).
+    fnt.py          ->  Verify constants used in the FNT; Python demo for the
+                        O(N**2) discrete transform.
+
+    matrix-transform.txt -> Proof for the Matrix Fourier Transform used in
+                            fourstep.c.
+    six-step.txt         -> Show that the algorithm used in sixstep.c is
+                            a variant of the Matrix Fourier Transform.
+    mulmod-64.txt        -> Proof for the mulmod64 algorithm from
+                            umodarith.h.
+    mulmod-ppro.txt      -> Proof for the x87 FPU modular multiplication
+                            from umodarith.h.
+    umodarith.lisp       -> ACL2 proofs for many functions from umodarith.h.
+
+
+Library Author
+==============
+
+  Stefan Krah <[email protected]>
+
+
+

+ 443 - 367
mpdecimal/basearith.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2010 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -52,30 +52,30 @@ mpd_uint_t
 _mpd_baseadd(mpd_uint_t *w, const mpd_uint_t *u, const mpd_uint_t *v,
              mpd_size_t m, mpd_size_t n)
 {
-	mpd_uint_t s;
-	mpd_uint_t carry = 0;
-	mpd_size_t i;
-
-	assert(n > 0 && m >= n);
-
-	/* add n members of u and v */
-	for (i = 0; i < n; i++) {
-		s = u[i] + (v[i] + carry);
-		carry = (s < u[i]) | (s >= MPD_RADIX);
-		w[i] = carry ? s-MPD_RADIX : s;
-	}
-	/* if there is a carry, propagate it */
-	for (; carry && i < m; i++) {
-		s = u[i] + carry;
-		carry = (s == MPD_RADIX);
-		w[i] = carry ? 0 : s;
-	}
-	/* copy the rest of u */
-	for (; i < m; i++) {
-		w[i] = u[i];
-	}
-
-	return carry;
+    mpd_uint_t s;
+    mpd_uint_t carry = 0;
+    mpd_size_t i;
+
+    assert(n > 0 && m >= n);
+
+    /* add n members of u and v */
+    for (i = 0; i < n; i++) {
+        s = u[i] + (v[i] + carry);
+        carry = (s < u[i]) | (s >= MPD_RADIX);
+        w[i] = carry ? s-MPD_RADIX : s;
+    }
+    /* if there is a carry, propagate it */
+    for (; carry && i < m; i++) {
+        s = u[i] + carry;
+        carry = (s == MPD_RADIX);
+        w[i] = carry ? 0 : s;
+    }
+    /* copy the rest of u */
+    for (; i < m; i++) {
+        w[i] = u[i];
+    }
+
+    return carry;
 }
 
 /*
@@ -85,70 +85,72 @@ _mpd_baseadd(mpd_uint_t *w, const mpd_uint_t *u, const mpd_uint_t *v,
 void
 _mpd_baseaddto(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n)
 {
-	mpd_uint_t s;
-	mpd_uint_t carry = 0;
-	mpd_size_t i;
-
-	if (n == 0) return;
-
-	/* add n members of u to w */
-	for (i = 0; i < n; i++) {
-		s = w[i] + (u[i] + carry);
-		carry = (s < w[i]) | (s >= MPD_RADIX);
-		w[i] = carry ? s-MPD_RADIX : s;
-	}
-	/* if there is a carry, propagate it */
-	for (; carry; i++) {
-		s = w[i] + carry;
-		carry = (s == MPD_RADIX);
-		w[i] = carry ? 0 : s;
-	}
+    mpd_uint_t s;
+    mpd_uint_t carry = 0;
+    mpd_size_t i;
+
+    if (n == 0) return;
+
+    /* add n members of u to w */
+    for (i = 0; i < n; i++) {
+        s = w[i] + (u[i] + carry);
+        carry = (s < w[i]) | (s >= MPD_RADIX);
+        w[i] = carry ? s-MPD_RADIX : s;
+    }
+    /* if there is a carry, propagate it */
+    for (; carry; i++) {
+        s = w[i] + carry;
+        carry = (s == MPD_RADIX);
+        w[i] = carry ? 0 : s;
+    }
 }
 
 /*
  * Add v to w (len m). The calling function has to handle a possible
- * final carry.
+ * final carry. Assumption: m > 0.
  */
 mpd_uint_t
 _mpd_shortadd(mpd_uint_t *w, mpd_size_t m, mpd_uint_t v)
 {
-	mpd_uint_t s;
-	mpd_uint_t carry = 0;
-	mpd_size_t i;
-
-	/* add v to u */
-	s = w[0] + v;
-	carry = (s < v) | (s >= MPD_RADIX);
-	w[0] = carry ? s-MPD_RADIX : s;
-
-	/* if there is a carry, propagate it */
-	for (i = 1; carry && i < m; i++) {
-		s = w[i] + carry;
-		carry = (s == MPD_RADIX);
-		w[i] = carry ? 0 : s;
-	}
-
-	return carry;
+    mpd_uint_t s;
+    mpd_uint_t carry;
+    mpd_size_t i;
+
+    assert(m > 0);
+
+    /* add v to w */
+    s = w[0] + v;
+    carry = (s < v) | (s >= MPD_RADIX);
+    w[0] = carry ? s-MPD_RADIX : s;
+
+    /* if there is a carry, propagate it */
+    for (i = 1; carry && i < m; i++) {
+        s = w[i] + carry;
+        carry = (s == MPD_RADIX);
+        w[i] = carry ? 0 : s;
+    }
+
+    return carry;
 }
 
 /* Increment u. The calling function has to handle a possible carry. */
 mpd_uint_t
 _mpd_baseincr(mpd_uint_t *u, mpd_size_t n)
 {
-	mpd_uint_t s;
-	mpd_uint_t carry = 1;
-	mpd_size_t i;
+    mpd_uint_t s;
+    mpd_uint_t carry = 1;
+    mpd_size_t i;
 
-	assert(n > 0);
+    assert(n > 0);
 
-	/* if there is a carry, propagate it */
-	for (i = 0; carry && i < n; i++) {
-		s = u[i] + carry;
-		carry = (s == MPD_RADIX);
-		u[i] = carry ? 0 : s;
-	}
+    /* if there is a carry, propagate it */
+    for (i = 0; carry && i < n; i++) {
+        s = u[i] + carry;
+        carry = (s == MPD_RADIX);
+        u[i] = carry ? 0 : s;
+    }
 
-	return carry;
+    return carry;
 }
 
 /*
@@ -160,28 +162,28 @@ void
 _mpd_basesub(mpd_uint_t *w, const mpd_uint_t *u, const mpd_uint_t *v,
              mpd_size_t m, mpd_size_t n)
 {
-	mpd_uint_t d;
-	mpd_uint_t borrow = 0;
-	mpd_size_t i;
-
-	assert(m > 0 && n > 0);
-
-	/* subtract n members of v from u */
-	for (i = 0; i < n; i++) {
-		d = u[i] - (v[i] + borrow);
-		borrow = (u[i] < d);
-		w[i] = borrow ? d + MPD_RADIX : d;
-	}
-	/* if there is a borrow, propagate it */
-	for (; borrow && i < m; i++) {
-		d = u[i] - borrow;
-		borrow = (u[i] == 0);
-		w[i] = borrow ? MPD_RADIX-1 : d;
-	}
-	/* copy the rest of u */
-	for (; i < m; i++) {
-		w[i] = u[i];
-	}
+    mpd_uint_t d;
+    mpd_uint_t borrow = 0;
+    mpd_size_t i;
+
+    assert(m > 0 && n > 0);
+
+    /* subtract n members of v from u */
+    for (i = 0; i < n; i++) {
+        d = u[i] - (v[i] + borrow);
+        borrow = (u[i] < d);
+        w[i] = borrow ? d + MPD_RADIX : d;
+    }
+    /* if there is a borrow, propagate it */
+    for (; borrow && i < m; i++) {
+        d = u[i] - borrow;
+        borrow = (u[i] == 0);
+        w[i] = borrow ? MPD_RADIX-1 : d;
+    }
+    /* copy the rest of u */
+    for (; i < m; i++) {
+        w[i] = u[i];
+    }
 }
 
 /*
@@ -191,45 +193,45 @@ _mpd_basesub(mpd_uint_t *w, const mpd_uint_t *u, const mpd_uint_t *v,
 void
 _mpd_basesubfrom(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n)
 {
-	mpd_uint_t d;
-	mpd_uint_t borrow = 0;
-	mpd_size_t i;
-
-	if (n == 0) return;
-
-	/* subtract n members of u from w */
-	for (i = 0; i < n; i++) {
-		d = w[i] - (u[i] + borrow);
-		borrow = (w[i] < d);
-		w[i] = borrow ? d + MPD_RADIX : d;
-	}
-	/* if there is a borrow, propagate it */
-	for (; borrow; i++) {
-		d = w[i] - borrow;
-		borrow = (w[i] == 0);
-		w[i] = borrow ? MPD_RADIX-1 : d;
-	}
+    mpd_uint_t d;
+    mpd_uint_t borrow = 0;
+    mpd_size_t i;
+
+    if (n == 0) return;
+
+    /* subtract n members of u from w */
+    for (i = 0; i < n; i++) {
+        d = w[i] - (u[i] + borrow);
+        borrow = (w[i] < d);
+        w[i] = borrow ? d + MPD_RADIX : d;
+    }
+    /* if there is a borrow, propagate it */
+    for (; borrow; i++) {
+        d = w[i] - borrow;
+        borrow = (w[i] == 0);
+        w[i] = borrow ? MPD_RADIX-1 : d;
+    }
 }
 
 /* w := product of u (len n) and v (single word) */
 void
 _mpd_shortmul(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n, mpd_uint_t v)
 {
-	mpd_uint_t hi, lo;
-	mpd_uint_t carry = 0;
-	mpd_size_t i;
+    mpd_uint_t hi, lo;
+    mpd_uint_t carry = 0;
+    mpd_size_t i;
 
-	assert(n > 0);
+    assert(n > 0);
 
-	for (i=0; i < n; i++) {
+    for (i=0; i < n; i++) {
 
-		_mpd_mul_words(&hi, &lo, u[i], v);
-		lo = carry + lo;
-		if (lo < carry) hi++;
+        _mpd_mul_words(&hi, &lo, u[i], v);
+        lo = carry + lo;
+        if (lo < carry) hi++;
 
-		_mpd_div_words_r(&carry, &w[i], hi, lo);
-	}
-	w[i] = carry;
+        _mpd_div_words_r(&carry, &w[i], hi, lo);
+    }
+    w[i] = carry;
 }
 
 /*
@@ -241,26 +243,26 @@ void
 _mpd_basemul(mpd_uint_t *w, const mpd_uint_t *u, const mpd_uint_t *v,
              mpd_size_t m, mpd_size_t n)
 {
-	mpd_uint_t hi, lo;
-	mpd_uint_t carry;
-	mpd_size_t i, j;
-
-	assert(m > 0 && n > 0);
-
-	for (j=0; j < n; j++) {
-		carry = 0;
-		for (i=0; i < m; i++) {
-
-			_mpd_mul_words(&hi, &lo, u[i], v[j]);
-			lo = w[i+j] + lo;
-			if (lo < w[i+j]) hi++;
-			lo = carry + lo;
-			if (lo < carry) hi++;
-
-			_mpd_div_words_r(&carry, &w[i+j], hi, lo);
-		}
-		w[j+m] = carry;
-	}
+    mpd_uint_t hi, lo;
+    mpd_uint_t carry;
+    mpd_size_t i, j;
+
+    assert(m > 0 && n > 0);
+
+    for (j=0; j < n; j++) {
+        carry = 0;
+        for (i=0; i < m; i++) {
+
+            _mpd_mul_words(&hi, &lo, u[i], v[j]);
+            lo = w[i+j] + lo;
+            if (lo < w[i+j]) hi++;
+            lo = carry + lo;
+            if (lo < carry) hi++;
+
+            _mpd_div_words_r(&carry, &w[i+j], hi, lo);
+        }
+        w[j+m] = carry;
+    }
 }
 
 /*
@@ -270,29 +272,29 @@ _mpd_basemul(mpd_uint_t *w, const mpd_uint_t *u, const mpd_uint_t *v,
 mpd_uint_t
 _mpd_shortdiv(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n, mpd_uint_t v)
 {
-	mpd_uint_t hi, lo;
-	mpd_uint_t rem = 0;
-	mpd_size_t i;
+    mpd_uint_t hi, lo;
+    mpd_uint_t rem = 0;
+    mpd_size_t i;
 
-	assert(n > 0);
+    assert(n > 0);
 
-	for (i=n-1; i != MPD_SIZE_MAX; i--) {
+    for (i=n-1; i != MPD_SIZE_MAX; i--) {
 
-		_mpd_mul_words(&hi, &lo, rem, MPD_RADIX);
-		lo = u[i] + lo;
-		if (lo < u[i]) hi++;
+        _mpd_mul_words(&hi, &lo, rem, MPD_RADIX);
+        lo = u[i] + lo;
+        if (lo < u[i]) hi++;
 
-		_mpd_div_words(&w[i], &rem, hi, lo, v);
-	}
+        _mpd_div_words(&w[i], &rem, hi, lo, v);
+    }
 
-	return rem;
+    return rem;
 }
 
 /*
  * Knuth, TAOCP Volume 2, 4.3.1:
  *     q, r := quotient and remainder of uconst (len nplusm)
  *             divided by vconst (len n)
- *     nplusm > n
+ *     nplusm >= n
  *
  * If r is not NULL, r will contain the remainder. If r is NULL, the
  * return value indicates if there is a remainder: 1 for true, 0 for
@@ -303,94 +305,93 @@ _mpd_basedivmod(mpd_uint_t *q, mpd_uint_t *r,
                 const mpd_uint_t *uconst, const mpd_uint_t *vconst,
                 mpd_size_t nplusm, mpd_size_t n)
 {
-	mpd_uint_t ustatic[MPD_MINALLOC_MAX];
-	mpd_uint_t vstatic[MPD_MINALLOC_MAX];
-	mpd_uint_t *u = ustatic;
-	mpd_uint_t *v = vstatic;
-	mpd_uint_t d, qhat, rhat, w2[2];
-	mpd_uint_t hi, lo, x;
-	mpd_uint_t carry;
-	mpd_size_t i, j, m;
-	int retval = 0;
-
-	assert(n > 1 && nplusm >= n);
-	m = sub_size_t(nplusm, n);
-
-	/* D1: normalize */
-	d = MPD_RADIX / (vconst[n-1] + 1);
-
-	if (nplusm >= MPD_MINALLOC_MAX) {
-		if ((u = mpd_calloc(nplusm+1, sizeof *u)) == NULL) {
-			return -1;
-		}
-	}
-	if (n >= MPD_MINALLOC_MAX) {
-		if ((v = mpd_calloc(n+1, sizeof *v)) == NULL) {
-			mpd_free(u);
-			return -1;
-		}
-	}
-
-	_mpd_shortmul(u, uconst, nplusm, d);
-	_mpd_shortmul(v, vconst, n, d);
-
-	/* D2: loop */
-	rhat = 0;
-	for (j=m; j != MPD_SIZE_MAX; j--) {
-
-		/* D3: calculate qhat and rhat */
-		rhat = _mpd_shortdiv(w2, u+j+n-1, 2, v[n-1]);
-		qhat = w2[1] * MPD_RADIX + w2[0];
-
-		while (1) {
-			if (qhat < MPD_RADIX) {
-				_mpd_singlemul(w2, qhat, v[n-2]);
-				if (w2[1] <= rhat) {
-					if (w2[1] != rhat || w2[0] <= u[j+n-2]) {
-						break;
-					}
-				}
-			}
-			qhat -= 1;
-			rhat += v[n-1];
-			if (rhat < v[n-1] || rhat >= MPD_RADIX) {
-				break;
-			}
-		}
-		/* D4: multiply and subtract */
-		carry = 0;
-		for (i=0; i <= n; i++) {
-
-			_mpd_mul_words(&hi, &lo, qhat, v[i]);
-
-			lo = carry + lo;
-			if (lo < carry) hi++;
-
-			_mpd_div_words_r(&hi, &lo, hi, lo);
-
-			x = u[i+j] - lo;
-			carry = (u[i+j] < x);
-			u[i+j] = carry ? x+MPD_RADIX : x;
-			carry += hi;
-		}
-		q[j] = qhat;
-		/* D5: test remainder */
-		if (carry) {
-			q[j] -= 1;
-			/* D6: add back */
-			(void)_mpd_baseadd(u+j, u+j, v, n+1, n);
-		}
-	}
-
-	/* D8: unnormalize */
-	if (r != NULL) {
-		_mpd_shortdiv(r, u, n, d);
-		/* we are not interested in the return value here */
-		retval = 0;
-	}
-	else {
-		retval = !_mpd_isallzero(u, n);
-	}
+    mpd_uint_t ustatic[MPD_MINALLOC_MAX];
+    mpd_uint_t vstatic[MPD_MINALLOC_MAX];
+    mpd_uint_t *u = ustatic;
+    mpd_uint_t *v = vstatic;
+    mpd_uint_t d, qhat, rhat, w2[2];
+    mpd_uint_t hi, lo, x;
+    mpd_uint_t carry;
+    mpd_size_t i, j, m;
+    int retval = 0;
+
+    assert(n > 1 && nplusm >= n);
+    m = sub_size_t(nplusm, n);
+
+    /* D1: normalize */
+    d = MPD_RADIX / (vconst[n-1] + 1);
+
+    if (nplusm >= MPD_MINALLOC_MAX) {
+        if ((u = mpd_alloc(nplusm+1, sizeof *u)) == NULL) {
+            return -1;
+        }
+    }
+    if (n >= MPD_MINALLOC_MAX) {
+        if ((v = mpd_alloc(n+1, sizeof *v)) == NULL) {
+            mpd_free(u);
+            return -1;
+        }
+    }
+
+    _mpd_shortmul(u, uconst, nplusm, d);
+    _mpd_shortmul(v, vconst, n, d);
+
+    /* D2: loop */
+    for (j=m; j != MPD_SIZE_MAX; j--) {
+
+        /* D3: calculate qhat and rhat */
+        rhat = _mpd_shortdiv(w2, u+j+n-1, 2, v[n-1]);
+        qhat = w2[1] * MPD_RADIX + w2[0];
+
+        while (1) {
+            if (qhat < MPD_RADIX) {
+                _mpd_singlemul(w2, qhat, v[n-2]);
+                if (w2[1] <= rhat) {
+                    if (w2[1] != rhat || w2[0] <= u[j+n-2]) {
+                        break;
+                    }
+                }
+            }
+            qhat -= 1;
+            rhat += v[n-1];
+            if (rhat < v[n-1] || rhat >= MPD_RADIX) {
+                break;
+            }
+        }
+        /* D4: multiply and subtract */
+        carry = 0;
+        for (i=0; i <= n; i++) {
+
+            _mpd_mul_words(&hi, &lo, qhat, v[i]);
+
+            lo = carry + lo;
+            if (lo < carry) hi++;
+
+            _mpd_div_words_r(&hi, &lo, hi, lo);
+
+            x = u[i+j] - lo;
+            carry = (u[i+j] < x);
+            u[i+j] = carry ? x+MPD_RADIX : x;
+            carry += hi;
+        }
+        q[j] = qhat;
+        /* D5: test remainder */
+        if (carry) {
+            q[j] -= 1;
+            /* D6: add back */
+            (void)_mpd_baseadd(u+j, u+j, v, n+1, n);
+        }
+    }
+
+    /* D8: unnormalize */
+    if (r != NULL) {
+        _mpd_shortdiv(r, u, n, d);
+        /* we are not interested in the return value here */
+        retval = 0;
+    }
+    else {
+        retval = !_mpd_isallzero(u, n);
+    }
 
 
 if (u != ustatic) mpd_free(u);
@@ -398,105 +399,155 @@ if (v != vstatic) mpd_free(v);
 return retval;
 }
 
-/* Leftshift of src by shift digits; src may equal dest. */
+/*
+ * Left shift of src by 'shift' digits; src may equal dest.
+ *
+ *  dest := area of n mpd_uint_t with space for srcdigits+shift digits.
+ *  src  := coefficient with length m.
+ *
+ * The case splits in the function are non-obvious. The following
+ * equations might help:
+ *
+ *  Let msdigits denote the number of digits in the most significant
+ *  word of src. Then 1 <= msdigits <= rdigits.
+ *
+ *   1) shift = q * rdigits + r
+ *   2) srcdigits = qsrc * rdigits + msdigits
+ *   3) destdigits = shift + srcdigits
+ *                 = q * rdigits + r + qsrc * rdigits + msdigits
+ *                 = q * rdigits + (qsrc * rdigits + (r + msdigits))
+ *
+ *  The result has q zero words, followed by the coefficient that
+ *  is left-shifted by r. The case r == 0 is trivial. For r > 0, it
+ *  is important to keep in mind that we always read m source words,
+ *  but write m+1 destination words if r + msdigits > rdigits, m words
+ *  otherwise.
+ */
 void
 _mpd_baseshiftl(mpd_uint_t *dest, mpd_uint_t *src, mpd_size_t n, mpd_size_t m,
                 mpd_size_t shift)
 {
 #if defined(__GNUC__) && !defined(__INTEL_COMPILER) && !defined(__clang__)
-	/* spurious uninitialized warnings */
-	mpd_uint_t l=l, lprev=lprev, h=h;
+    /* spurious uninitialized warnings */
+    mpd_uint_t l=l, lprev=lprev, h=h;
 #else
-	mpd_uint_t l, lprev, h;
+    mpd_uint_t l, lprev, h;
 #endif
-	mpd_uint_t q, r;
-	mpd_uint_t ph;
-
-	assert(m > 0 && n >= m);
-
-	_mpd_div_word(&q, &r, (mpd_uint_t)shift, MPD_RDIGITS);
-
-	if (r != 0) {
-
-		ph = mpd_pow10[r];
-
-		--m; --n;
-		_mpd_divmod_pow10(&h, &lprev, src[m--], MPD_RDIGITS-r);
-		if (h != 0) {
-			dest[n--] = h;
-		}
-		for (; m != MPD_SIZE_MAX; m--,n--) {
-			_mpd_divmod_pow10(&h, &l, src[m], MPD_RDIGITS-r);
-			dest[n] = ph * lprev + h;
-			lprev = l;
-		}
-		dest[q] = ph * lprev;
-	}
-	else {
-		while (--m != MPD_SIZE_MAX) {
-			dest[m+q] = src[m];
-		}
-	}
-
-	mpd_uint_zero(dest, q);
+    mpd_uint_t q, r;
+    mpd_uint_t ph;
+
+    assert(m > 0 && n >= m);
+
+    _mpd_div_word(&q, &r, (mpd_uint_t)shift, MPD_RDIGITS);
+
+    if (r != 0) {
+
+        ph = mpd_pow10[r];
+
+        --m; --n;
+        _mpd_divmod_pow10(&h, &lprev, src[m--], MPD_RDIGITS-r);
+        if (h != 0) { /* r + msdigits > rdigits <==> h != 0 */
+            dest[n--] = h;
+        }
+        /* write m-1 shifted words */
+        for (; m != MPD_SIZE_MAX; m--,n--) {
+            _mpd_divmod_pow10(&h, &l, src[m], MPD_RDIGITS-r);
+            dest[n] = ph * lprev + h;
+            lprev = l;
+        }
+        /* write least significant word */
+        dest[q] = ph * lprev;
+    }
+    else {
+        while (--m != MPD_SIZE_MAX) {
+            dest[m+q] = src[m];
+        }
+    }
+
+    mpd_uint_zero(dest, q);
 }
 
-/* Rightshift of src by shift digits; src may equal dest. */
+/*
+ * Right shift of src by 'shift' digits; src may equal dest.
+ * Assumption: srcdigits-shift > 0.
+ *
+ *  dest := area with space for srcdigits-shift digits.
+ *  src  := coefficient with length 'slen'.
+ *
+ * The case splits in the function rely on the following equations:
+ *
+ *  Let msdigits denote the number of digits in the most significant
+ *  word of src. Then 1 <= msdigits <= rdigits.
+ *
+ *  1) shift = q * rdigits + r
+ *  2) srcdigits = qsrc * rdigits + msdigits
+ *  3) destdigits = srcdigits - shift
+ *                = qsrc * rdigits + msdigits - (q * rdigits + r)
+ *                = (qsrc - q) * rdigits + msdigits - r
+ *
+ * Since destdigits > 0 and 1 <= msdigits <= rdigits:
+ *
+ *  4) qsrc >= q
+ *  5) qsrc == q  ==>  msdigits > r
+ *
+ * The result has slen-q words if msdigits > r, slen-q-1 words otherwise.
+ */
 mpd_uint_t
 _mpd_baseshiftr(mpd_uint_t *dest, mpd_uint_t *src, mpd_size_t slen,
                 mpd_size_t shift)
 {
 #if defined(__GNUC__) && !defined(__INTEL_COMPILER) && !defined(__clang__)
-	/* spurious uninitialized warnings */
-	mpd_uint_t l=l, h=h, hprev=hprev; /* low, high, previous high */
+    /* spurious uninitialized warnings */
+    mpd_uint_t l=l, h=h, hprev=hprev; /* low, high, previous high */
 #else
-	mpd_uint_t l, h, hprev; /* low, high, previous high */
+    mpd_uint_t l, h, hprev; /* low, high, previous high */
 #endif
-	mpd_uint_t rnd, rest;   /* rounding digit, rest */
-	mpd_uint_t q, r;
-	mpd_size_t i, j;
-	mpd_uint_t ph;
-
-	assert(slen > 0);
-
-	_mpd_div_word(&q, &r, (mpd_uint_t)shift, MPD_RDIGITS);
-
-	rnd = rest = 0;
-	if (r != 0) {
-
-		ph = mpd_pow10[MPD_RDIGITS-r];
-
-		_mpd_divmod_pow10(&hprev, &rest, src[q], r);
-		_mpd_divmod_pow10(&rnd, &rest, rest, r-1);
-
-		if (rest == 0 && q > 0) {
-			rest = !_mpd_isallzero(src, q);
-		}
-		h = hprev;
-		for (j=0,i=q+1; i<slen; i++,j++) {
-			_mpd_divmod_pow10(&h, &l, src[i], r);
-			dest[j] = ph * l + hprev;
-			hprev = h;
-		}
-		if (hprev != 0) {
-			dest[j] = hprev;
-		}
-	}
-	else {
-		if (q > 0) {
-			_mpd_divmod_pow10(&rnd, &rest, src[q-1], MPD_RDIGITS-1);
-			/* is there any non-zero digit below rnd? */
-			if (rest == 0) rest = !_mpd_isallzero(src, q-1);
-		}
-		for (j = 0; j < slen-q; j++) {
-			dest[j] = src[q+j];
-		}
-	}
-
-	/* 0-4  ==> rnd+rest < 0.5   */
-	/* 5    ==> rnd+rest == 0.5  */
-	/* 6-9  ==> rnd+rest > 0.5   */
-	return (rnd == 0 || rnd == 5) ? rnd + !!rest : rnd;
+    mpd_uint_t rnd, rest;   /* rounding digit, rest */
+    mpd_uint_t q, r;
+    mpd_size_t i, j;
+    mpd_uint_t ph;
+
+    assert(slen > 0);
+
+    _mpd_div_word(&q, &r, (mpd_uint_t)shift, MPD_RDIGITS);
+
+    rnd = rest = 0;
+    if (r != 0) {
+
+        ph = mpd_pow10[MPD_RDIGITS-r];
+
+        _mpd_divmod_pow10(&hprev, &rest, src[q], r);
+        _mpd_divmod_pow10(&rnd, &rest, rest, r-1);
+
+        if (rest == 0 && q > 0) {
+            rest = !_mpd_isallzero(src, q);
+        }
+        /* write slen-q-1 words */
+        for (j=0,i=q+1; i<slen; i++,j++) {
+            _mpd_divmod_pow10(&h, &l, src[i], r);
+            dest[j] = ph * l + hprev;
+            hprev = h;
+        }
+        /* write most significant word */
+        if (hprev != 0) { /* always the case if slen==q-1 */
+            dest[j] = hprev;
+        }
+    }
+    else {
+        if (q > 0) {
+            _mpd_divmod_pow10(&rnd, &rest, src[q-1], MPD_RDIGITS-1);
+            /* is there any non-zero digit below rnd? */
+            if (rest == 0) rest = !_mpd_isallzero(src, q-1);
+        }
+        for (j = 0; j < slen-q; j++) {
+            dest[j] = src[q+j];
+        }
+    }
+
+    /* 0-4  ==> rnd+rest < 0.5   */
+    /* 5    ==> rnd+rest == 0.5  */
+    /* 6-9  ==> rnd+rest > 0.5   */
+    return (rnd == 0 || rnd == 5) ? rnd + !!rest : rnd;
 }
 
 
@@ -506,50 +557,75 @@ _mpd_baseshiftr(mpd_uint_t *dest, mpd_uint_t *src, mpd_size_t slen,
 
 /*
  * Add v to w (len m). The calling function has to handle a possible
- * final carry.
+ * final carry. Assumption: m > 0.
  */
 mpd_uint_t
 _mpd_shortadd_b(mpd_uint_t *w, mpd_size_t m, mpd_uint_t v, mpd_uint_t b)
 {
-	mpd_uint_t s;
-	mpd_uint_t carry = 0;
-	mpd_size_t i;
-
-	/* add v to u */
-	s = w[0] + v;
-	carry = (s < v) | (s >= b);
-	w[0] = carry ? s-b : s;
-
-	/* if there is a carry, propagate it */
-	for (i = 1; carry && i < m; i++) {
-		s = w[i] + carry;
-		carry = (s == b);
-		w[i] = carry ? 0 : s;
-	}
-
-	return carry;
+    mpd_uint_t s;
+    mpd_uint_t carry;
+    mpd_size_t i;
+
+    assert(m > 0);
+
+    /* add v to w */
+    s = w[0] + v;
+    carry = (s < v) | (s >= b);
+    w[0] = carry ? s-b : s;
+
+    /* if there is a carry, propagate it */
+    for (i = 1; carry && i < m; i++) {
+        s = w[i] + carry;
+        carry = (s == b);
+        w[i] = carry ? 0 : s;
+    }
+
+    return carry;
+}
+
+/* w := product of u (len n) and v (single word). Return carry. */
+mpd_uint_t
+_mpd_shortmul_c(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n, mpd_uint_t v)
+{
+    mpd_uint_t hi, lo;
+    mpd_uint_t carry = 0;
+    mpd_size_t i;
+
+    assert(n > 0);
+
+    for (i=0; i < n; i++) {
+
+        _mpd_mul_words(&hi, &lo, u[i], v);
+        lo = carry + lo;
+        if (lo < carry) hi++;
+
+        _mpd_div_words_r(&carry, &w[i], hi, lo);
+    }
+
+    return carry;
 }
 
 /* w := product of u (len n) and v (single word) */
-void
+mpd_uint_t
 _mpd_shortmul_b(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n,
                 mpd_uint_t v, mpd_uint_t b)
 {
-	mpd_uint_t hi, lo;
-	mpd_uint_t carry = 0;
-	mpd_size_t i;
+    mpd_uint_t hi, lo;
+    mpd_uint_t carry = 0;
+    mpd_size_t i;
+
+    assert(n > 0);
 
-	assert(n > 0);
+    for (i=0; i < n; i++) {
 
-	for (i=0; i < n; i++) {
+        _mpd_mul_words(&hi, &lo, u[i], v);
+        lo = carry + lo;
+        if (lo < carry) hi++;
 
-		_mpd_mul_words(&hi, &lo, u[i], v);
-		lo = carry + lo;
-		if (lo < carry) hi++;
+        _mpd_div_words(&carry, &w[i], hi, lo, b);
+    }
 
-		_mpd_div_words(&carry, &w[i], hi, lo, b);
-	}
-	w[i] = carry;
+    return carry;
 }
 
 /*
@@ -560,22 +636,22 @@ mpd_uint_t
 _mpd_shortdiv_b(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n,
                 mpd_uint_t v, mpd_uint_t b)
 {
-	mpd_uint_t hi, lo;
-	mpd_uint_t rem = 0;
-	mpd_size_t i;
+    mpd_uint_t hi, lo;
+    mpd_uint_t rem = 0;
+    mpd_size_t i;
 
-	assert(n > 0);
+    assert(n > 0);
 
-	for (i=n-1; i != MPD_SIZE_MAX; i--) {
+    for (i=n-1; i != MPD_SIZE_MAX; i--) {
 
-		_mpd_mul_words(&hi, &lo, rem, b);
-		lo = u[i] + lo;
-		if (lo < u[i]) hi++;
+        _mpd_mul_words(&hi, &lo, rem, b);
+        lo = u[i] + lo;
+        if (lo < u[i]) hi++;
 
-		_mpd_div_words(&w[i], &rem, hi, lo, v);
-	}
+        _mpd_div_words(&w[i], &rem, hi, lo, v);
+    }
 
-	return rem;
+    return rem;
 }
 
 

+ 104 - 62
mpdecimal/basearith.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2010 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -35,6 +35,10 @@
 #include "typearith.h"
 
 
+/* Internal header file: all symbols have local scope in the DSO */
+MPD_PRAGMA(MPD_HIDE_SYMBOLS_START)
+
+
 mpd_uint_t _mpd_baseadd(mpd_uint_t *w, const mpd_uint_t *u, const mpd_uint_t *v,
                         mpd_size_t m, mpd_size_t n);
 void _mpd_baseaddto(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n);
@@ -49,8 +53,10 @@ void _mpd_basemul(mpd_uint_t *w, const mpd_uint_t *u, const mpd_uint_t *v,
                   mpd_size_t m, mpd_size_t n);
 void _mpd_shortmul(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n,
                    mpd_uint_t v);
-void _mpd_shortmul_b(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n,
-                     mpd_uint_t v, mpd_uint_t b);
+mpd_uint_t _mpd_shortmul_c(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n,
+                           mpd_uint_t v);
+mpd_uint_t _mpd_shortmul_b(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n,
+                           mpd_uint_t v, mpd_uint_t b);
 mpd_uint_t _mpd_shortdiv(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n,
                          mpd_uint_t v);
 mpd_uint_t _mpd_shortdiv_b(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n,
@@ -73,77 +79,110 @@ extern const mpd_uint_t mprime_rdx;
  * Conference on Programming Language Design and Implementation.
  *
  * http://gmplib.org/~tege/divcnst-pldi94.pdf
+ *
+ * Variables from the paper and their translations (See section 8):
+ *
+ *  N := 64
+ *  d := MPD_RADIX
+ *  l := 64
+ *  m' := floor((2**(64+64) - 1)/MPD_RADIX) - 2**64
+ *
+ * Since N-l == 0:
+ *
+ *  dnorm := d
+ *  n2 := hi
+ *  n10 := lo
+ *
+ * ACL2 proof: mpd-div-words-r-correct
  */
 static inline void
 _mpd_div_words_r(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t hi, mpd_uint_t lo)
 {
-	mpd_uint_t n_adj, h, l, t;
-	mpd_uint_t n1_neg;
-
-	n1_neg = (lo & (1ULL<<63)) ? MPD_UINT_MAX : 0;
-	n_adj = lo + (n1_neg & MPD_RADIX);
-
-	_mpd_mul_words(&h, &l, mprime_rdx, hi-n1_neg);
-	l = l + n_adj;
-	if (l < n_adj) h++;
-	t = h + hi; /* q1 */
-
-	t = MPD_UINT_MAX - t;
-
-	_mpd_mul_words(&h, &l, t, MPD_RADIX);
-	l = l + lo;
-	if (l < lo) h++;
-	h += hi;
-	h -= MPD_RADIX;
-
-	*q = (h - t);
-	*r = l + (MPD_RADIX & h);
+    mpd_uint_t n_adj, h, l, t;
+    mpd_uint_t n1_neg;
+
+    /* n1_neg = if lo >= 2**63 then MPD_UINT_MAX else 0 */
+    n1_neg = (lo & (1ULL<<63)) ? MPD_UINT_MAX : 0;
+    /* n_adj = if lo >= 2**63 then lo+MPD_RADIX else lo */
+    n_adj = lo + (n1_neg & MPD_RADIX);
+
+    /* (h, l) = if lo >= 2**63 then m'*(hi+1) else m'*hi */
+    _mpd_mul_words(&h, &l, mprime_rdx, hi-n1_neg);
+    l = l + n_adj;
+    if (l < n_adj) h++;
+    t = h + hi;
+    /* At this point t == qest, with q == qest or q == qest+1:
+     *   1) 0 <= 2**64*hi + lo - qest*MPD_RADIX < 2*MPD_RADIX
+     */
+
+    /* t = 2**64-1 - qest = 2**64 - (qest+1) */
+    t = MPD_UINT_MAX - t;
+
+    /* (h, l) = 2**64*MPD_RADIX - (qest+1)*MPD_RADIX */
+    _mpd_mul_words(&h, &l, t, MPD_RADIX);
+    l = l + lo;
+    if (l < lo) h++;
+    h += hi;
+    h -= MPD_RADIX;
+    /* (h, l) = 2**64*hi + lo - (qest+1)*MPD_RADIX (mod 2**128)
+     * Case q == qest+1:
+     *     a) h == 0, l == r
+     *     b) q := h - t == qest+1
+     *     c) r := l
+     * Case q == qest:
+     *     a) h == MPD_UINT_MAX, l == 2**64-(MPD_RADIX-r)
+     *     b) q := h - t == qest
+     *     c) r := l + MPD_RADIX = r
+     */
+
+    *q = (h - t);
+    *r = l + (MPD_RADIX & h);
 }
 #else
 static inline void
 _mpd_div_words_r(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t hi, mpd_uint_t lo)
 {
-	_mpd_div_words(q, r, hi, lo, MPD_RADIX);
+    _mpd_div_words(q, r, hi, lo, MPD_RADIX);
 }
 #endif
 
 
-/* Multiply two single base b words, store result in array w[2]. */
+/* Multiply two single base MPD_RADIX words, store result in array w[2]. */
 static inline void
 _mpd_singlemul(mpd_uint_t w[2], mpd_uint_t u, mpd_uint_t v)
 {
-	mpd_uint_t hi, lo;
+    mpd_uint_t hi, lo;
 
-	_mpd_mul_words(&hi, &lo, u, v);
-	_mpd_div_words_r(&w[1], &w[0], hi, lo);
+    _mpd_mul_words(&hi, &lo, u, v);
+    _mpd_div_words_r(&w[1], &w[0], hi, lo);
 }
 
-/* Multiply u (len 2) and v (len 1 or 2). */
+/* Multiply u (len 2) and v (len m, 1 <= m <= 2). */
 static inline void
 _mpd_mul_2_le2(mpd_uint_t w[4], mpd_uint_t u[2], mpd_uint_t v[2], mpd_ssize_t m)
 {
-	mpd_uint_t hi, lo;
-
-	_mpd_mul_words(&hi, &lo, u[0], v[0]);
-	_mpd_div_words_r(&w[1], &w[0], hi, lo);
-
-	_mpd_mul_words(&hi, &lo, u[1], v[0]);
-	lo = w[1] + lo;
-	if (lo < w[1]) hi++;
-	_mpd_div_words_r(&w[2], &w[1], hi, lo);
-	if (m == 1) return;
-
-	_mpd_mul_words(&hi, &lo, u[0], v[1]);
-	lo = w[1] + lo;
-	if (lo < w[1]) hi++;
-	_mpd_div_words_r(&w[3], &w[1], hi, lo);
-
-	_mpd_mul_words(&hi, &lo, u[1], v[1]);
-	lo = w[2] + lo;
-	if (lo < w[2]) hi++;
-	lo = w[3] + lo;
-	if (lo < w[3]) hi++;
-	_mpd_div_words_r(&w[3], &w[2], hi, lo);
+    mpd_uint_t hi, lo;
+
+    _mpd_mul_words(&hi, &lo, u[0], v[0]);
+    _mpd_div_words_r(&w[1], &w[0], hi, lo);
+
+    _mpd_mul_words(&hi, &lo, u[1], v[0]);
+    lo = w[1] + lo;
+    if (lo < w[1]) hi++;
+    _mpd_div_words_r(&w[2], &w[1], hi, lo);
+    if (m == 1) return;
+
+    _mpd_mul_words(&hi, &lo, u[0], v[1]);
+    lo = w[1] + lo;
+    if (lo < w[1]) hi++;
+    _mpd_div_words_r(&w[3], &w[1], hi, lo);
+
+    _mpd_mul_words(&hi, &lo, u[1], v[1]);
+    lo = w[2] + lo;
+    if (lo < w[2]) hi++;
+    lo = w[3] + lo;
+    if (lo < w[3]) hi++;
+    _mpd_div_words_r(&w[3], &w[2], hi, lo);
 }
 
 
@@ -154,26 +193,29 @@ _mpd_mul_2_le2(mpd_uint_t w[4], mpd_uint_t u[2], mpd_uint_t v[2], mpd_ssize_t m)
 static inline int
 _mpd_isallzero(const mpd_uint_t *data, mpd_ssize_t len)
 {
-	while (--len >= 0) {
-		if (data[len] != 0) return 0;
-	}
-	return 1;
+    while (--len >= 0) {
+        if (data[len] != 0) return 0;
+    }
+    return 1;
 }
 
 /*
- * Test if all words from data[len-1] to data[0] are MPD_RADIX-1 (all nines).
- * Assumes that len > 0.
+ * Test if all full words from data[len-1] to data[0] are MPD_RADIX-1
+ * (all nines). Return true if len == 0.
  */
 static inline int
 _mpd_isallnine(const mpd_uint_t *data, mpd_ssize_t len)
 {
-	while (--len >= 0) {
-		if (data[len] != MPD_RADIX-1) return 0;
-	}
-	return 1;
+    while (--len >= 0) {
+        if (data[len] != MPD_RADIX-1) return 0;
+    }
+    return 1;
 }
 
 
+MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
+
+
 #endif /* BASEARITH_H */
 
 

+ 68 - 72
mpdecimal/bits.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2010 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -34,155 +34,151 @@
 #include <stdio.h>
 
 
-/* Check if n is a power of 2 */
+/* Check if n is a power of 2. */
 static inline int
 ispower2(mpd_size_t n)
 {
-	return n != 0 && (n & (n-1)) == 0;
+    return n != 0 && (n & (n-1)) == 0;
 }
 
 #if defined(ANSI)
 /*
- * Returns the most significant bit position of n from 0 to 32 (64).
- * Caller has to make sure that n is not 0.
+ * Return the most significant bit position of n from 0 to 31 (63).
+ * Assumptions: n != 0.
  */
 static inline int
 mpd_bsr(mpd_size_t n)
 {
-	int pos = 0;
-	mpd_size_t tmp;
+    int pos = 0;
+    mpd_size_t tmp;
 
 #ifdef CONFIG_64
-	tmp = n >> 32;
-	if (tmp != 0) { n = tmp; pos += 32; }
+    tmp = n >> 32;
+    if (tmp != 0) { n = tmp; pos += 32; }
 #endif
-	tmp = n >> 16;
-	if (tmp != 0) { n = tmp; pos += 16; }
-	tmp = n >> 8;
-	if (tmp != 0) { n = tmp; pos += 8; }
-	tmp = n >> 4;
-	if (tmp != 0) { n = tmp; pos += 4; }
-	tmp = n >> 2;
-	if (tmp != 0) { n = tmp; pos += 2; }
-	tmp = n >> 1;
-	if (tmp != 0) { n = tmp; pos += 1; }
-
-	return pos + (int)n - 1;
+    tmp = n >> 16;
+    if (tmp != 0) { n = tmp; pos += 16; }
+    tmp = n >> 8;
+    if (tmp != 0) { n = tmp; pos += 8; }
+    tmp = n >> 4;
+    if (tmp != 0) { n = tmp; pos += 4; }
+    tmp = n >> 2;
+    if (tmp != 0) { n = tmp; pos += 2; }
+    tmp = n >> 1;
+    if (tmp != 0) { n = tmp; pos += 1; }
+
+    return pos + (int)n - 1;
 }
 
 /*
- * Returns the least significant bit position of n from 0 to 32 (64).
- * Caller has to make sure that n is not 0.
+ * Return the least significant bit position of n from 0 to 31 (63).
+ * Assumptions: n != 0.
  */
 static inline int
 mpd_bsf(mpd_size_t n)
 {
-	int pos;
+    int pos;
 
 #ifdef CONFIG_64
-	pos = 63;
-	if (n & 0x00000000FFFFFFFFULL) { pos -= 32; } else { n >>= 32; }
-	if (n & 0x000000000000FFFFULL) { pos -= 16; } else { n >>= 16; }
-	if (n & 0x00000000000000FFULL) { pos -=  8; } else { n >>=  8; }
-	if (n & 0x000000000000000FULL) { pos -=  4; } else { n >>=  4; }
-	if (n & 0x0000000000000003ULL) { pos -=  2; } else { n >>=  2; }
-	if (n & 0x0000000000000001ULL) { pos -=  1; }
+    pos = 63;
+    if (n & 0x00000000FFFFFFFFULL) { pos -= 32; } else { n >>= 32; }
+    if (n & 0x000000000000FFFFULL) { pos -= 16; } else { n >>= 16; }
+    if (n & 0x00000000000000FFULL) { pos -=  8; } else { n >>=  8; }
+    if (n & 0x000000000000000FULL) { pos -=  4; } else { n >>=  4; }
+    if (n & 0x0000000000000003ULL) { pos -=  2; } else { n >>=  2; }
+    if (n & 0x0000000000000001ULL) { pos -=  1; }
 #else
-	pos = 31;
-	if (n & 0x000000000000FFFFUL) { pos -= 16; } else { n >>= 16; }
-	if (n & 0x00000000000000FFUL) { pos -=  8; } else { n >>=  8; }
-	if (n & 0x000000000000000FUL) { pos -=  4; } else { n >>=  4; }
-	if (n & 0x0000000000000003UL) { pos -=  2; } else { n >>=  2; }
-	if (n & 0x0000000000000001UL) { pos -=  1; }
+    pos = 31;
+    if (n & 0x000000000000FFFFUL) { pos -= 16; } else { n >>= 16; }
+    if (n & 0x00000000000000FFUL) { pos -=  8; } else { n >>=  8; }
+    if (n & 0x000000000000000FUL) { pos -=  4; } else { n >>=  4; }
+    if (n & 0x0000000000000003UL) { pos -=  2; } else { n >>=  2; }
+    if (n & 0x0000000000000001UL) { pos -=  1; }
 #endif
-	return pos;
+    return pos;
 }
 /* END ANSI */
 
 #elif defined(ASM)
 /*
- * Bit scan reverse.
- * Caller has to make sure that a is not 0.
+ * Bit scan reverse. Assumptions: a != 0.
  */
 static inline int
 mpd_bsr(mpd_size_t a)
 {
-	mpd_size_t retval;
+    mpd_size_t retval;
 
-	__asm__ (
+    __asm__ (
 #ifdef CONFIG_64
-		"bsrq %1, %0\n\t"
+        "bsrq %1, %0\n\t"
 #else
-		"bsr %1, %0\n\t"
+        "bsr %1, %0\n\t"
 #endif
-		:"=r" (retval)
-		:"r" (a)
-		:"cc"
-	);
+        :"=r" (retval)
+        :"r" (a)
+        :"cc"
+    );
 
-	return (int)retval;
+    return (int)retval;
 }
 
 /*
- * Bit scan forward.
- * Caller has to make sure that a is not 0.
+ * Bit scan forward. Assumptions: a != 0.
  */
 static inline int
 mpd_bsf(mpd_size_t a)
 {
-	mpd_size_t retval;
+    mpd_size_t retval;
 
-	__asm__ (
+    __asm__ (
 #ifdef CONFIG_64
-		"bsfq %1, %0\n\t"
+        "bsfq %1, %0\n\t"
 #else
-		"bsf %1, %0\n\t"
+        "bsf %1, %0\n\t"
 #endif
-		:"=r" (retval)
-		:"r" (a)
-		:"cc"
-	);
+        :"=r" (retval)
+        :"r" (a)
+        :"cc"
+    );
 
-	return (int)retval;
+    return (int)retval;
 }
 /* END ASM */
 
 #elif defined(MASM)
 #include <intrin.h>
 /*
- * Bit scan reverse.
- * Caller has to make sure that a is not 0.
+ * Bit scan reverse. Assumptions: a != 0.
  */
 static inline int __cdecl
 mpd_bsr(mpd_size_t a)
 {
-	unsigned long retval;
+    unsigned long retval;
 
 #ifdef CONFIG_64
-	_BitScanReverse64(&retval, a);
+    _BitScanReverse64(&retval, a);
 #else
-	_BitScanReverse(&retval, a);
+    _BitScanReverse(&retval, a);
 #endif
 
-	return (int)retval;
+    return (int)retval;
 }
 
 /*
- * Bit scan forward.
- * Caller has to make sure that a is not 0.
+ * Bit scan forward. Assumptions: a != 0.
  */
 static inline int __cdecl
 mpd_bsf(mpd_size_t a)
 {
-	unsigned long retval;
+    unsigned long retval;
 
 #ifdef CONFIG_64
-	_BitScanForward64(&retval, a);
+    _BitScanForward64(&retval, a);
 #else
-	_BitScanForward(&retval, a);
+    _BitScanForward(&retval, a);
 #endif
 
-	return (int)retval;
+    return (int)retval;
 }
 /* END MASM (_MSC_VER) */
 #else

+ 12 - 12
mpdecimal/constants.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2010 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -113,20 +113,20 @@
 #endif
 
 const char *mpd_round_string[MPD_ROUND_GUARD] = {
-	"ROUND_UP",          /* round away from 0               */
-	"ROUND_DOWN",        /* round toward 0 (truncate)       */
-	"ROUND_CEILING",     /* round toward +infinity          */
-	"ROUND_FLOOR",       /* round toward -infinity          */
-	"ROUND_HALF_UP",     /* 0.5 is rounded up               */
-	"ROUND_HALF_DOWN",   /* 0.5 is rounded down             */
-	"ROUND_HALF_EVEN",   /* 0.5 is rounded to even          */
-	"ROUND_05UP",        /* round zero or five away from 0  */
-	"ROUND_TRUNC",       /* truncate, but set infinity      */
+    "ROUND_UP",          /* round away from 0               */
+    "ROUND_DOWN",        /* round toward 0 (truncate)       */
+    "ROUND_CEILING",     /* round toward +infinity          */
+    "ROUND_FLOOR",       /* round toward -infinity          */
+    "ROUND_HALF_UP",     /* 0.5 is rounded up               */
+    "ROUND_HALF_DOWN",   /* 0.5 is rounded down             */
+    "ROUND_HALF_EVEN",   /* 0.5 is rounded to even          */
+    "ROUND_05UP",        /* round zero or five away from 0  */
+    "ROUND_TRUNC",       /* truncate, but set infinity      */
 };
 
 const char *mpd_clamp_string[MPD_CLAMP_GUARD] = {
-	"CLAMP_DEFAULT",
-	"CLAMP_IEEE_754"
+    "CLAMP_DEFAULT",
+    "CLAMP_IEEE_754"
 };
 
 

+ 8 - 1
mpdecimal/constants.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2010 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -33,6 +33,10 @@
 #include "mpdecimal.h"
 
 
+/* Internal header file: all symbols have local scope in the DSO */
+MPD_PRAGMA(MPD_HIDE_SYMBOLS_START)
+
+
 /* choice of optimized functions */
 #if defined(CONFIG_64)
 /* x64 */
@@ -77,6 +81,9 @@ extern const mpd_uint_t LH_P1P2;
 extern const mpd_uint_t UH_P1P2;
 
 
+MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
+
+
 #endif /* CONSTANTS_H */
 
 

+ 122 - 136
mpdecimal/context.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2010 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -44,260 +44,246 @@ mpd_dflt_traphandler(mpd_context_t *ctx UNUSED)
 void (* mpd_traphandler)(mpd_context_t *) = mpd_dflt_traphandler;
 
 
+/* Set guaranteed minimum number of coefficient words. The function may
+   be used once at program start. Setting MPD_MINALLOC to out-of-bounds
+   values is a catastrophic error, so in that case the function exits rather
+   than relying on the user to check a return value. */
 void
 mpd_setminalloc(mpd_ssize_t n)
 {
-	static int minalloc_is_set = 0;
-
-	if (minalloc_is_set) {
-		mpd_err_warn("mpd_setminalloc: ignoring request to set "
-		             "MPD_MINALLOC a second time\n");
-		return;
-	}
-	if (n < MPD_MINALLOC_MIN || n > MPD_MINALLOC_MAX) {
-		mpd_err_fatal("illegal value for MPD_MINALLOC"); /* GCOV_NOT_REACHED */
-	}
-	MPD_MINALLOC = n;
-	minalloc_is_set = 1;
+    static int minalloc_is_set = 0;
+
+    if (minalloc_is_set) {
+        mpd_err_warn("mpd_setminalloc: ignoring request to set "
+                     "MPD_MINALLOC a second time\n");
+        return;
+    }
+    if (n < MPD_MINALLOC_MIN || n > MPD_MINALLOC_MAX) {
+        mpd_err_fatal("illegal value for MPD_MINALLOC"); /* GCOV_NOT_REACHED */
+    }
+    MPD_MINALLOC = n;
+    minalloc_is_set = 1;
 }
 
 void
 mpd_init(mpd_context_t *ctx, mpd_ssize_t prec)
 {
-	mpd_ssize_t ideal_minalloc;
+    mpd_ssize_t ideal_minalloc;
 
-	mpd_defaultcontext(ctx);
+    mpd_defaultcontext(ctx);
 
-	if (!mpd_qsetprec(ctx, prec)) {
-		mpd_addstatus_raise(ctx, MPD_Invalid_context);
-		return;
-	}
+    if (!mpd_qsetprec(ctx, prec)) {
+        mpd_addstatus_raise(ctx, MPD_Invalid_context);
+        return;
+    }
 
-	ideal_minalloc = 2 * ((prec+MPD_RDIGITS-1) / MPD_RDIGITS);
-	if (ideal_minalloc < MPD_MINALLOC_MIN) ideal_minalloc = MPD_MINALLOC_MIN;
-	if (ideal_minalloc > MPD_MINALLOC_MAX) ideal_minalloc = MPD_MINALLOC_MAX;
+    ideal_minalloc = 2 * ((prec+MPD_RDIGITS-1) / MPD_RDIGITS);
+    if (ideal_minalloc < MPD_MINALLOC_MIN) ideal_minalloc = MPD_MINALLOC_MIN;
+    if (ideal_minalloc > MPD_MINALLOC_MAX) ideal_minalloc = MPD_MINALLOC_MAX;
 
-	mpd_setminalloc(ideal_minalloc);
+    mpd_setminalloc(ideal_minalloc);
 }
 
 void
 mpd_maxcontext(mpd_context_t *ctx)
 {
-	ctx->prec=MPD_MAX_PREC;
-	ctx->emax=MPD_MAX_EMAX;
-	ctx->emin=MPD_MIN_EMIN;
-	ctx->round=MPD_ROUND_HALF_EVEN;
-	ctx->traps=MPD_Traps;
-	ctx->status=0;
-	ctx->newtrap=0;
-	ctx->clamp=0;
-	ctx->allcr=1;
-}
-
-void
-mpd_maxcontext_plus(mpd_context_t *workctx, const mpd_context_t *ctx)
-{
-	workctx->prec = ctx->prec > MPD_MAX_PREC ? ctx->prec : MPD_MAX_PREC;
-	workctx->emax = ctx->emax > MPD_MAX_EMAX ? ctx->emax : MPD_MAX_EMAX;
-	workctx->emin = ctx->emin < MPD_MIN_EMIN ? ctx->emin : MPD_MIN_EMIN;
-	workctx->round=MPD_ROUND_HALF_EVEN;
-	workctx->traps=MPD_Traps;
-	workctx->status=0;
-	workctx->newtrap=0;
-	workctx->clamp=0;
-	workctx->allcr=1;
+    ctx->prec=MPD_MAX_PREC;
+    ctx->emax=MPD_MAX_EMAX;
+    ctx->emin=MPD_MIN_EMIN;
+    ctx->round=MPD_ROUND_HALF_EVEN;
+    ctx->traps=MPD_Traps;
+    ctx->status=0;
+    ctx->newtrap=0;
+    ctx->clamp=0;
+    ctx->allcr=1;
 }
 
 void
 mpd_defaultcontext(mpd_context_t *ctx)
 {
-	ctx->prec=2*MPD_RDIGITS;
-	ctx->emax=MPD_MAX_EMAX;
-	ctx->emin=MPD_MIN_EMIN;
-	ctx->round=MPD_ROUND_HALF_UP;
-	ctx->traps=MPD_Traps;
-	ctx->status=0;
-	ctx->newtrap=0;
-	ctx->clamp=0;
-	ctx->allcr=1;
+    ctx->prec=2*MPD_RDIGITS;
+    ctx->emax=MPD_MAX_EMAX;
+    ctx->emin=MPD_MIN_EMIN;
+    ctx->round=MPD_ROUND_HALF_UP;
+    ctx->traps=MPD_Traps;
+    ctx->status=0;
+    ctx->newtrap=0;
+    ctx->clamp=0;
+    ctx->allcr=1;
 }
 
 void
 mpd_basiccontext(mpd_context_t *ctx)
 {
-	ctx->prec=9;
-	ctx->emax=MPD_MAX_EMAX;
-	ctx->emin=MPD_MIN_EMIN;
-	ctx->round=MPD_ROUND_HALF_UP;
-	ctx->traps=MPD_Traps|MPD_Clamped;
-	ctx->status=0;
-	ctx->newtrap=0;
-	ctx->clamp=0;
-	ctx->allcr=1;
+    ctx->prec=9;
+    ctx->emax=MPD_MAX_EMAX;
+    ctx->emin=MPD_MIN_EMIN;
+    ctx->round=MPD_ROUND_HALF_UP;
+    ctx->traps=MPD_Traps|MPD_Clamped;
+    ctx->status=0;
+    ctx->newtrap=0;
+    ctx->clamp=0;
+    ctx->allcr=1;
 }
 
 int
 mpd_ieee_context(mpd_context_t *ctx, int bits)
 {
-	if (bits <= 0 || bits > MPD_IEEE_CONTEXT_MAX_BITS || bits % 32) {
-		return -1;
-	}
-
-	ctx->prec = 9 * (bits/32) - 2;
-	ctx->emax = 3 * ((mpd_ssize_t)1<<(bits/16+3));
-	ctx->emin = 1 - ctx->emax;
-	ctx->round=MPD_ROUND_HALF_EVEN;
-	ctx->traps=0;
-	ctx->status=0;
-	ctx->newtrap=0;
-	ctx->clamp=1;
-	ctx->allcr=1;
-
-	return 0;
+    if (bits <= 0 || bits > MPD_IEEE_CONTEXT_MAX_BITS || bits % 32) {
+        return -1;
+    }
+
+    ctx->prec = 9 * (bits/32) - 2;
+    ctx->emax = 3 * ((mpd_ssize_t)1<<(bits/16+3));
+    ctx->emin = 1 - ctx->emax;
+    ctx->round=MPD_ROUND_HALF_EVEN;
+    ctx->traps=0;
+    ctx->status=0;
+    ctx->newtrap=0;
+    ctx->clamp=1;
+    ctx->allcr=1;
+
+    return 0;
 }
 
 mpd_ssize_t
 mpd_getprec(const mpd_context_t *ctx)
 {
-	return ctx->prec;
+    return ctx->prec;
 }
 
 mpd_ssize_t
 mpd_getemax(const mpd_context_t *ctx)
 {
-	return ctx->emax;
+    return ctx->emax;
 }
 
 mpd_ssize_t
 mpd_getemin(const mpd_context_t *ctx)
 {
-	return ctx->emin;
+    return ctx->emin;
 }
 
 int
 mpd_getround(const mpd_context_t *ctx)
 {
-	return ctx->round;
+    return ctx->round;
 }
 
 uint32_t
 mpd_gettraps(const mpd_context_t *ctx)
 {
-	return ctx->traps;
+    return ctx->traps;
 }
 
 uint32_t
 mpd_getstatus(const mpd_context_t *ctx)
 {
-	return ctx->status;
+    return ctx->status;
 }
 
 int
 mpd_getclamp(const mpd_context_t *ctx)
 {
-	return ctx->clamp;
+    return ctx->clamp;
 }
 
 int
 mpd_getcr(const mpd_context_t *ctx)
 {
-	return ctx->allcr;
+    return ctx->allcr;
 }
 
 
 int
 mpd_qsetprec(mpd_context_t *ctx, mpd_ssize_t prec)
 {
-	if (prec <= 0 || prec > MPD_MAX_PREC) {
-		return 0;
-	}
-	ctx->prec = prec;
-	return 1;
+    if (prec <= 0 || prec > MPD_MAX_PREC) {
+        return 0;
+    }
+    ctx->prec = prec;
+    return 1;
 }
 
 int
 mpd_qsetemax(mpd_context_t *ctx, mpd_ssize_t emax)
 {
-	if (emax < 0 || emax > MPD_MAX_EMAX) {
-		return 0;
-	}
-	ctx->emax = emax;
-	return 1;
+    if (emax < 0 || emax > MPD_MAX_EMAX) {
+        return 0;
+    }
+    ctx->emax = emax;
+    return 1;
 }
 
 int
 mpd_qsetemin(mpd_context_t *ctx, mpd_ssize_t emin)
 {
-	if (emin > 0 || emin < MPD_MIN_EMIN) {
-		return 0;
-	}
-	ctx->emin = emin;
-	return 1;
+    if (emin > 0 || emin < MPD_MIN_EMIN) {
+        return 0;
+    }
+    ctx->emin = emin;
+    return 1;
 }
 
 int
 mpd_qsetround(mpd_context_t *ctx, int round)
 {
-	int i;
-
-	for (i = 0; i < MPD_ROUND_GUARD; i++) {
-		if (i == round) {
-			ctx->round = round;
-			return 1;
-		}
-	}
-	return 0;
+    if (!(0 <= round && round < MPD_ROUND_GUARD)) {
+        return 0;
+    }
+    ctx->round = round;
+    return 1;
 }
 
 int
 mpd_qsettraps(mpd_context_t *ctx, uint32_t traps)
 {
-	if (traps > MPD_Max_status) {
-		return 0;
-	}
-	ctx->traps = traps;
-	return 1;
+    if (traps > MPD_Max_status) {
+        return 0;
+    }
+    ctx->traps = traps;
+    return 1;
 }
 
 int
 mpd_qsetstatus(mpd_context_t *ctx, uint32_t flags)
 {
-	if (flags > MPD_Max_status) {
-		return 0;
-	}
-	ctx->status = flags;
-	return 1;
+    if (flags > MPD_Max_status) {
+        return 0;
+    }
+    ctx->status = flags;
+    return 1;
 }
 
 int
 mpd_qsetclamp(mpd_context_t *ctx, int c)
 {
-	if (c != 0 && c != 1) {
-		return 0;
-	}
-	ctx->clamp = c;
-	return 1;
+    if (c != 0 && c != 1) {
+        return 0;
+    }
+    ctx->clamp = c;
+    return 1;
 }
 
 int
 mpd_qsetcr(mpd_context_t *ctx, int c)
 {
-	if (c != 0 && c != 1) {
-		return 0;
-	}
-	ctx->allcr = c;
-	return 1;
+    if (c != 0 && c != 1) {
+        return 0;
+    }
+    ctx->allcr = c;
+    return 1;
 }
 
 
 void
 mpd_addstatus_raise(mpd_context_t *ctx, uint32_t flags)
 {
-	ctx->status |= flags;
-	if (flags&ctx->traps) {
-		ctx->newtrap = (flags&ctx->traps);
-		mpd_traphandler(ctx);
-	}
+    ctx->status |= flags;
+    if (flags&ctx->traps) {
+        ctx->newtrap = (flags&ctx->traps);
+        mpd_traphandler(ctx);
+    }
 }
 
 

+ 118 - 114
mpdecimal/convolute.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2010 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -38,133 +38,137 @@
 #include "convolute.h"
 
 
+/* Bignum: Fast convolution using the Number Theoretic Transform. Used for
+   the multiplication of very large coefficients. */
+
+
 /* Convolute the data in c1 and c2. Result is in c1. */
 int
 fnt_convolute(mpd_uint_t *c1, mpd_uint_t *c2, mpd_size_t n, int modnum)
 {
-	int (*fnt)(mpd_uint_t *, mpd_size_t, int);
-	int (*inv_fnt)(mpd_uint_t *, mpd_size_t, int);
+    int (*fnt)(mpd_uint_t *, mpd_size_t, int);
+    int (*inv_fnt)(mpd_uint_t *, mpd_size_t, int);
 #ifdef PPRO
-	double dmod;
-	uint32_t dinvmod[3];
+    double dmod;
+    uint32_t dinvmod[3];
 #endif
-	mpd_uint_t n_inv, umod;
-	mpd_size_t i;
-
-
-	SETMODULUS(modnum);
-	n_inv = POWMOD(n, (umod-2));
-
-	if (ispower2(n)) {
-		if (n > SIX_STEP_THRESHOLD) {
-			fnt = six_step_fnt;
-			inv_fnt = inv_six_step_fnt;
-		}
-		else {
-			fnt = std_fnt;
-			inv_fnt = std_inv_fnt;
-		}
-	}
-	else {
-		fnt = four_step_fnt;
-		inv_fnt = inv_four_step_fnt;
-	}
-
-	if (!fnt(c1, n, modnum)) {
-		return 0;
-	}
-	if (!fnt(c2, n, modnum)) {
-		return 0;
-	}
-	for (i = 0; i < n-1; i += 2) {
-		mpd_uint_t x0 = c1[i];
-		mpd_uint_t y0 = c2[i];
-		mpd_uint_t x1 = c1[i+1];
-		mpd_uint_t y1 = c2[i+1];
-		MULMOD2(&x0, y0, &x1, y1);
-		c1[i] = x0;
-		c1[i+1] = x1;
-	}
-
-	if (!inv_fnt(c1, n, modnum)) {
-		return 0;
-	}
-	for (i = 0; i < n-3; i += 4) {
-		mpd_uint_t x0 = c1[i];
-		mpd_uint_t x1 = c1[i+1];
-		mpd_uint_t x2 = c1[i+2];
-		mpd_uint_t x3 = c1[i+3];
-		MULMOD2C(&x0, &x1, n_inv);
-		MULMOD2C(&x2, &x3, n_inv);
-		c1[i] = x0;
-		c1[i+1] = x1;
-		c1[i+2] = x2;
-		c1[i+3] = x3;
-	}
-
-	return 1;
+    mpd_uint_t n_inv, umod;
+    mpd_size_t i;
+
+
+    SETMODULUS(modnum);
+    n_inv = POWMOD(n, (umod-2));
+
+    if (ispower2(n)) {
+        if (n > SIX_STEP_THRESHOLD) {
+            fnt = six_step_fnt;
+            inv_fnt = inv_six_step_fnt;
+        }
+        else {
+            fnt = std_fnt;
+            inv_fnt = std_inv_fnt;
+        }
+    }
+    else {
+        fnt = four_step_fnt;
+        inv_fnt = inv_four_step_fnt;
+    }
+
+    if (!fnt(c1, n, modnum)) {
+        return 0;
+    }
+    if (!fnt(c2, n, modnum)) {
+        return 0;
+    }
+    for (i = 0; i < n-1; i += 2) {
+        mpd_uint_t x0 = c1[i];
+        mpd_uint_t y0 = c2[i];
+        mpd_uint_t x1 = c1[i+1];
+        mpd_uint_t y1 = c2[i+1];
+        MULMOD2(&x0, y0, &x1, y1);
+        c1[i] = x0;
+        c1[i+1] = x1;
+    }
+
+    if (!inv_fnt(c1, n, modnum)) {
+        return 0;
+    }
+    for (i = 0; i < n-3; i += 4) {
+        mpd_uint_t x0 = c1[i];
+        mpd_uint_t x1 = c1[i+1];
+        mpd_uint_t x2 = c1[i+2];
+        mpd_uint_t x3 = c1[i+3];
+        MULMOD2C(&x0, &x1, n_inv);
+        MULMOD2C(&x2, &x3, n_inv);
+        c1[i] = x0;
+        c1[i+1] = x1;
+        c1[i+2] = x2;
+        c1[i+3] = x3;
+    }
+
+    return 1;
 }
 
 /* Autoconvolute the data in c1. Result is in c1. */
 int
 fnt_autoconvolute(mpd_uint_t *c1, mpd_size_t n, int modnum)
 {
-	int (*fnt)(mpd_uint_t *, mpd_size_t, int);
-	int (*inv_fnt)(mpd_uint_t *, mpd_size_t, int);
+    int (*fnt)(mpd_uint_t *, mpd_size_t, int);
+    int (*inv_fnt)(mpd_uint_t *, mpd_size_t, int);
 #ifdef PPRO
-	double dmod;
-	uint32_t dinvmod[3];
+    double dmod;
+    uint32_t dinvmod[3];
 #endif
-	mpd_uint_t n_inv, umod;
-	mpd_size_t i;
-
-
-	SETMODULUS(modnum);
-	n_inv = POWMOD(n, (umod-2));
-
-	if (ispower2(n)) {
-		if (n > SIX_STEP_THRESHOLD) {
-			fnt = six_step_fnt;
-			inv_fnt = inv_six_step_fnt;
-		}
-		else {
-			fnt = std_fnt;
-			inv_fnt = std_inv_fnt;
-		}
-	}
-	else {
-		fnt = four_step_fnt;
-		inv_fnt = inv_four_step_fnt;
-	}
-
-	if (!fnt(c1, n, modnum)) {
-		return 0;
-	}
-	for (i = 0; i < n-1; i += 2) {
-		mpd_uint_t x0 = c1[i];
-		mpd_uint_t x1 = c1[i+1];
-		MULMOD2(&x0, x0, &x1, x1);
-		c1[i] = x0;
-		c1[i+1] = x1;
-	}
-
-	if (!inv_fnt(c1, n, modnum)) {
-		return 0;
-	}
-	for (i = 0; i < n-3; i += 4) {
-		mpd_uint_t x0 = c1[i];
-		mpd_uint_t x1 = c1[i+1];
-		mpd_uint_t x2 = c1[i+2];
-		mpd_uint_t x3 = c1[i+3];
-		MULMOD2C(&x0, &x1, n_inv);
-		MULMOD2C(&x2, &x3, n_inv);
-		c1[i] = x0;
-		c1[i+1] = x1;
-		c1[i+2] = x2;
-		c1[i+3] = x3;
-	}
-
-	return 1;
+    mpd_uint_t n_inv, umod;
+    mpd_size_t i;
+
+
+    SETMODULUS(modnum);
+    n_inv = POWMOD(n, (umod-2));
+
+    if (ispower2(n)) {
+        if (n > SIX_STEP_THRESHOLD) {
+            fnt = six_step_fnt;
+            inv_fnt = inv_six_step_fnt;
+        }
+        else {
+            fnt = std_fnt;
+            inv_fnt = std_inv_fnt;
+        }
+    }
+    else {
+        fnt = four_step_fnt;
+        inv_fnt = inv_four_step_fnt;
+    }
+
+    if (!fnt(c1, n, modnum)) {
+        return 0;
+    }
+    for (i = 0; i < n-1; i += 2) {
+        mpd_uint_t x0 = c1[i];
+        mpd_uint_t x1 = c1[i+1];
+        MULMOD2(&x0, x0, &x1, x1);
+        c1[i] = x0;
+        c1[i+1] = x1;
+    }
+
+    if (!inv_fnt(c1, n, modnum)) {
+        return 0;
+    }
+    for (i = 0; i < n-3; i += 4) {
+        mpd_uint_t x0 = c1[i];
+        mpd_uint_t x1 = c1[i+1];
+        mpd_uint_t x2 = c1[i+2];
+        mpd_uint_t x3 = c1[i+3];
+        MULMOD2C(&x0, &x1, n_inv);
+        MULMOD2C(&x2, &x3, n_inv);
+        c1[i] = x0;
+        c1[i+1] = x1;
+        c1[i+2] = x2;
+        c1[i+3] = x3;
+    }
+
+    return 1;
 }
 
 

+ 9 - 2
mpdecimal/convolute.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2010 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -33,11 +33,18 @@
 #include "mpdecimal.h"
 #include <stdio.h>
 
-#define SIX_STEP_THRESHOLD 4096
 
+/* Internal header file: all symbols have local scope in the DSO */
+MPD_PRAGMA(MPD_HIDE_SYMBOLS_START)
+
+
+#define SIX_STEP_THRESHOLD 4096
 
 int fnt_convolute(mpd_uint_t *c1, mpd_uint_t *c2, mpd_size_t n, int modnum);
 int fnt_autoconvolute(mpd_uint_t *c1, mpd_size_t n, int modnum);
 
 
+MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
+
+
 #endif

+ 79 - 88
mpdecimal/crt.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2010 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -34,64 +34,62 @@
 #include "crt.h"
 
 
-/*
- * Functions for arithmetic on triple-word mpd_uint_t numbers.
- */
+/* Bignum: Chinese Remainder Theorem, extends the maximum transform length. */
 
 
 /* Multiply P1P2 by v, store result in w. */
 static inline void
 _crt_mulP1P2_3(mpd_uint_t w[3], mpd_uint_t v)
 {
-	mpd_uint_t hi1, hi2, lo;
+    mpd_uint_t hi1, hi2, lo;
 
-	_mpd_mul_words(&hi1, &lo, LH_P1P2, v);
-	w[0] = lo;
+    _mpd_mul_words(&hi1, &lo, LH_P1P2, v);
+    w[0] = lo;
 
-	_mpd_mul_words(&hi2, &lo, UH_P1P2, v);
-	lo = hi1 + lo;
-	if (lo < hi1) hi2++;
+    _mpd_mul_words(&hi2, &lo, UH_P1P2, v);
+    lo = hi1 + lo;
+    if (lo < hi1) hi2++;
 
-	w[1] = lo;
-	w[2] = hi2;
+    w[1] = lo;
+    w[2] = hi2;
 }
 
 /* Add 3 words from v to w. The result is known to fit in w. */
 static inline void
 _crt_add3(mpd_uint_t w[3], mpd_uint_t v[3])
 {
-	mpd_uint_t carry;
-
-	w[0] = w[0] + v[0];
-	carry = (w[0] < v[0]);
+    mpd_uint_t carry;
+    mpd_uint_t s;
 
-	w[1] = w[1] + v[1];
-	if (w[1] < v[1]) w[2]++;
+    s = w[0] + v[0];
+    carry = (s < w[0]);
+    w[0] = s;
 
-	w[1] = w[1] + carry;
-	if (w[1] < carry) w[2]++;
+    s = w[1] + (v[1] + carry);
+    carry = (s < w[1]);
+    w[1] = s;
 
-	w[2] += v[2];
+    w[2] = w[2] + (v[2] + carry);
 }
 
 /* Divide 3 words in u by v, store result in w, return remainder. */
 static inline mpd_uint_t
 _crt_div3(mpd_uint_t *w, const mpd_uint_t *u, mpd_uint_t v)
 {
-	mpd_uint_t r1 = u[2];
-	mpd_uint_t r2;
+    mpd_uint_t r1 = u[2];
+    mpd_uint_t r2;
 
-	if (r1 < v) {
-		w[2] = 0;
-	}
-	else {
-		_mpd_div_word(&w[2], &r1, u[2], v); /* GCOV_NOT_REACHED */
-	}
+    if (r1 < v) {
+        w[2] = 0;
+    }
+    else {
+        _mpd_div_word(&w[2], &r1, u[2], v); /* GCOV_NOT_REACHED */
+    }
 
-	_mpd_div_words(&w[1], &r2, r1, u[1], v);
-	_mpd_div_words(&w[0], &r1, r2, u[0], v);
+    _mpd_div_words(&w[1], &r2, r1, u[1], v);
+    _mpd_div_words(&w[0], &r1, r2, u[0], v);
 
-	return r1;
+    return r1;
 }
 
 
@@ -99,90 +97,83 @@ _crt_div3(mpd_uint_t *w, const mpd_uint_t *u, mpd_uint_t v)
  * Chinese Remainder Theorem:
  * Algorithm from Joerg Arndt, "Matters Computational",
  * Chapter 37.4.1 [http://www.jjj.de/fxt/]
+ *
+ * See also Knuth, TAOCP, Volume 2, 4.3.2, exercise 7.
  */
 
 /*
  * CRT with carry: x1, x2, x3 contain numbers modulo p1, p2, p3. For each
- * triple of members of the arrays, find the unique z modulo p1*p2*p3.
- *
- * Overflow analysis for 32 bit:
+ * triple of members of the arrays, find the unique z modulo p1*p2*p3, with
+ * zmax = p1*p2*p3 - 1.
  *
- * carry[3] can hold cmax = 2**96-1. Let c_i denote the carry at the
- * beginning of the ith iteration. Let zmax be the maximum z.
+ * In each iteration of the loop, split z into result[i] = z % MPD_RADIX
+ * and carry = z / MPD_RADIX. Let N be the size of carry[] and cmax the
+ * maximum carry.
  *
- * cmax = 2**96-1      = 79228162514264337593543950335
- * zmax = (p1*p2*p3)-1 = 7711435583600944683209981953
+ * Limits for the 32-bit build:
  *
- * c_0 = 0
- * c_1 = (c_0 + zmax) / 10**9 = 7711435583600944683
- * c_2 = (c_1 + zmax) / 10**9 = 7711435591312380266
- * c_3 = (c_2 + zmax) / 10**9 = 7711435591312380274
- * c_4 = (c_3 + zmax) / 10**9 = 7711435591312380274
- * (...)
+ *   N    = 2**96
+ *   cmax = 7711435591312380274
  *
- * The carries do not increase, (c_i + zmax) cannot overflow.
+ * Limits for the 64 bit build:
  *
+ *   N    = 2**192
+ *   cmax = 627710135393475385904124401220046371710
  *
- * Overflow analysis for 64 bit:
+ * The following statements hold for both versions:
  *
- * cmax = 2**192-1     = 6277101735386680763835789423207666416102355444464034512895
- * zmax = (p1*p2*p3)-1 = 6277101353934753858413533876806988331203900781075588186113
+ *   1) cmax + zmax < N, so the addition does not overflow.
  *
- * c_0 = 0
- * c_1 = (c_0 + zmax) / 10**19 = 627710135393475385841353387680698833120
- * c_2 = (c_1 + zmax) / 10**19 = 627710135393475385904124401220046371704
- * c_3 = (c_2 + zmax) / 10**19 = 627710135393475385904124401220046371710
- * c_4 = (c_3 + zmax) / 10**19 = 627710135393475385904124401220046371710
- * (...)
+ *   2) (cmax + zmax) / MPD_RADIX == cmax.
  *
- * The carries do not increase. (c_i + zmax) cannot overflow.
+ *   3) If c <= cmax, then c_next = (c + zmax) / MPD_RADIX <= cmax.
  */
 void
 crt3(mpd_uint_t *x1, mpd_uint_t *x2, mpd_uint_t *x3, mpd_size_t rsize)
 {
-	mpd_uint_t p1 = mpd_moduli[P1];
-	mpd_uint_t umod;
+    mpd_uint_t p1 = mpd_moduli[P1];
+    mpd_uint_t umod;
 #ifdef PPRO
-	double dmod;
-	uint32_t dinvmod[3];
+    double dmod;
+    uint32_t dinvmod[3];
 #endif
-	mpd_uint_t a1, a2, a3;
-	mpd_uint_t s;
-	mpd_uint_t z[3], t[3];
-	mpd_uint_t carry[3] = {0,0,0};
-	mpd_uint_t hi, lo;
-	mpd_size_t i;
+    mpd_uint_t a1, a2, a3;
+    mpd_uint_t s;
+    mpd_uint_t z[3], t[3];
+    mpd_uint_t carry[3] = {0,0,0};
+    mpd_uint_t hi, lo;
+    mpd_size_t i;
 
-	for (i = 0; i < rsize; i++) {
+    for (i = 0; i < rsize; i++) {
 
-		a1 = x1[i];
-		a2 = x2[i];
-		a3 = x3[i];
+        a1 = x1[i];
+        a2 = x2[i];
+        a3 = x3[i];
 
-		SETMODULUS(P2);
-		s = ext_submod(a2, a1, umod);
-		s = MULMOD(s, INV_P1_MOD_P2);
+        SETMODULUS(P2);
+        s = ext_submod(a2, a1, umod);
+        s = MULMOD(s, INV_P1_MOD_P2);
 
-		_mpd_mul_words(&hi, &lo, s, p1);
-		lo = lo + a1;
-		if (lo < a1) hi++;
+        _mpd_mul_words(&hi, &lo, s, p1);
+        lo = lo + a1;
+        if (lo < a1) hi++;
 
-		SETMODULUS(P3);
-		s = dw_submod(a3, hi, lo, umod);
-		s = MULMOD(s, INV_P1P2_MOD_P3);
+        SETMODULUS(P3);
+        s = dw_submod(a3, hi, lo, umod);
+        s = MULMOD(s, INV_P1P2_MOD_P3);
 
-		z[0] = lo;
-		z[1] = hi;
-		z[2] = 0;
+        z[0] = lo;
+        z[1] = hi;
+        z[2] = 0;
 
-		_crt_mulP1P2_3(t, s);
-		_crt_add3(z, t);
-		_crt_add3(carry, z);
+        _crt_mulP1P2_3(t, s);
+        _crt_add3(z, t);
+        _crt_add3(carry, z);
 
-		x1[i] = _crt_div3(carry, carry, MPD_RADIX);
-	}
+        x1[i] = _crt_div3(carry, carry, MPD_RADIX);
+    }
 
-	assert(carry[0] == 0 && carry[1] == 0 && carry[2] == 0);
+    assert(carry[0] == 0 && carry[1] == 0 && carry[2] == 0);
 }
 
 

+ 8 - 1
mpdecimal/crt.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2010 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -34,7 +34,14 @@
 #include <stdio.h>
 
 
+/* Internal header file: all symbols have local scope in the DSO */
+MPD_PRAGMA(MPD_HIDE_SYMBOLS_START)
+
+
 void crt3(mpd_uint_t *x1, mpd_uint_t *x2, mpd_uint_t *x3, mpd_size_t nmemb);
 
 
+MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
+
+
 #endif

+ 88 - 78
mpdecimal/difradix2.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2010 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -35,27 +35,36 @@
 #include "difradix2.h"
 
 
+/* Bignum: The actual transform routine (decimation in frequency). */
+
+
 /*
- * Generate bit reversed words and carry out the permutation.
- * Algorithm due to Brent Lehmann, see Joerg Arndt, "Matters Computational",
- * Chapter 1.13.4. [http://www.jjj.de/fxt/]
+ * Generate index pairs (x, bitreverse(x)) and carry out the permutation.
+ * n must be a power of two.
+ * Algorithm due to Brent/Lehmann, see Joerg Arndt, "Matters Computational",
+ * Chapter 1.14.4. [http://www.jjj.de/fxt/]
  */
 static inline void
 bitreverse_permute(mpd_uint_t a[], mpd_size_t n)
 {
-	mpd_size_t x = 0;
-	mpd_size_t r = 0;
-	mpd_uint_t t;
-
-	do {
-		if (r > x) {
-			t = a[x];
-			a[x] = a[r];
-			a[r] = t;
-		}
-		x += 1;
-		r ^= (n - (n >> (mpd_bsf(x)+1)));
-	} while (x < n);
+    mpd_size_t x = 0;
+    mpd_size_t r = 0;
+    mpd_uint_t t;
+
+    do { /* Invariant: r = bitreverse(x) */
+        if (r > x) {
+            t = a[x];
+            a[x] = a[r];
+            a[r] = t;
+        }
+        /* Flip trailing consecutive 1 bits and the first zero bit
+         * that absorbs a possible carry. */
+        x += 1;
+        /* Mirror the operation on r: Flip n_trailing_zeros(x)+1
+           high bits of r. */
+        r ^= (n - (n >> (mpd_bsf(x)+1)));
+        /* The loop invariant is preserved. */
+    } while (x < n);
 }
 
 
@@ -63,101 +72,102 @@ bitreverse_permute(mpd_uint_t a[], mpd_size_t n)
 void
 fnt_dif2(mpd_uint_t a[], mpd_size_t n, struct fnt_params *tparams)
 {
-	mpd_uint_t *wtable = tparams->wtable;
-	mpd_uint_t umod;
+    mpd_uint_t *wtable = tparams->wtable;
+    mpd_uint_t umod;
 #ifdef PPRO
-	double dmod;
-	uint32_t dinvmod[3];
+    double dmod;
+    uint32_t dinvmod[3];
 #endif
-	mpd_uint_t u0, u1, v0, v1;
-	mpd_uint_t w, w0, w1, wstep;
-	mpd_size_t m ,mhalf;
-	mpd_size_t j, r;
+    mpd_uint_t u0, u1, v0, v1;
+    mpd_uint_t w, w0, w1, wstep;
+    mpd_size_t m, mhalf;
+    mpd_size_t j, r;
 
 
-	assert(ispower2(n));
-	assert(n >= 4);
+    assert(ispower2(n));
+    assert(n >= 4);
 
-	SETMODULUS(tparams->modnum);
+    SETMODULUS(tparams->modnum);
 
-	mhalf = n / 2;
-	for (j = 0; j < mhalf; j += 2) {
+    /* m == n */
+    mhalf = n / 2;
+    for (j = 0; j < mhalf; j += 2) {
 
-		w0 = wtable[j];
-		w1 = wtable[j+1];
+        w0 = wtable[j];
+        w1 = wtable[j+1];
 
-		u0 = a[j];
-		v0 = a[j+mhalf];
+        u0 = a[j];
+        v0 = a[j+mhalf];
 
-		u1 = a[j+1];
-		v1 = a[j+1+mhalf];
+        u1 = a[j+1];
+        v1 = a[j+1+mhalf];
 
-		a[j] = addmod(u0, v0, umod);
-		v0 = submod(u0, v0, umod);
+        a[j] = addmod(u0, v0, umod);
+        v0 = submod(u0, v0, umod);
 
-		a[j+1] = addmod(u1, v1, umod);
-		v1 = submod(u1, v1, umod);
+        a[j+1] = addmod(u1, v1, umod);
+        v1 = submod(u1, v1, umod);
 
-		MULMOD2(&v0, w0, &v1, w1);
+        MULMOD2(&v0, w0, &v1, w1);
 
-		a[j+mhalf] = v0;
-		a[j+1+mhalf] = v1;
+        a[j+mhalf] = v0;
+        a[j+1+mhalf] = v1;
 
-	}
+    }
 
-	wstep = 2;
-	for (m = n/2; m >= 2; m>>=1, wstep<<=1) {
+    wstep = 2;
+    for (m = n/2; m >= 2; m>>=1, wstep<<=1) {
 
-		mhalf = m / 2;
+        mhalf = m / 2;
 
-		/* j = 0 */
-		for (r = 0; r < n; r += 2*m) {
+        /* j == 0 */
+        for (r = 0; r < n; r += 2*m) {
 
-			u0 = a[r];
-			v0 = a[r+mhalf];
+            u0 = a[r];
+            v0 = a[r+mhalf];
 
-			u1 = a[m+r];
-			v1 = a[m+r+mhalf];
+            u1 = a[m+r];
+            v1 = a[m+r+mhalf];
 
-			a[r] = addmod(u0, v0, umod);
-			v0 = submod(u0, v0, umod);
+            a[r] = addmod(u0, v0, umod);
+            v0 = submod(u0, v0, umod);
 
-			a[m+r] = addmod(u1, v1, umod);
-			v1 = submod(u1, v1, umod);
+            a[m+r] = addmod(u1, v1, umod);
+            v1 = submod(u1, v1, umod);
 
-			a[r+mhalf] = v0;
-			a[m+r+mhalf] = v1;
-		}
+            a[r+mhalf] = v0;
+            a[m+r+mhalf] = v1;
+        }
 
-		for (j = 1; j < mhalf; j++) {
+        for (j = 1; j < mhalf; j++) {
 
-			w = wtable[j*wstep];
+            w = wtable[j*wstep];
 
-			for (r = 0; r < n; r += 2*m) {
+            for (r = 0; r < n; r += 2*m) {
 
-				u0 = a[r+j];
-				v0 = a[r+j+mhalf];
+                u0 = a[r+j];
+                v0 = a[r+j+mhalf];
 
-				u1 = a[m+r+j];
-				v1 = a[m+r+j+mhalf];
+                u1 = a[m+r+j];
+                v1 = a[m+r+j+mhalf];
 
-				a[r+j] = addmod(u0, v0, umod);
-				v0 = submod(u0, v0, umod);
+                a[r+j] = addmod(u0, v0, umod);
+                v0 = submod(u0, v0, umod);
 
-				a[m+r+j] = addmod(u1, v1, umod);
-				v1 = submod(u1, v1, umod);
+                a[m+r+j] = addmod(u1, v1, umod);
+                v1 = submod(u1, v1, umod);
 
-				MULMOD2C(&v0, &v1, w);
+                MULMOD2C(&v0, &v1, w);
 
-				a[r+j+mhalf] = v0;
-				a[m+r+j+mhalf] = v1;
-			}
+                a[r+j+mhalf] = v0;
+                a[m+r+j+mhalf] = v1;
+            }
 
-		}
+        }
 
-	}
+    }
 
-	bitreverse_permute(a, n);
+    bitreverse_permute(a, n);
 }
 
 

+ 8 - 1
mpdecimal/difradix2.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2010 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -35,7 +35,14 @@
 #include "numbertheory.h"
 
 
+/* Internal header file: all symbols have local scope in the DSO */
+MPD_PRAGMA(MPD_HIDE_SYMBOLS_START)
+
+
 void fnt_dif2(mpd_uint_t a[], mpd_size_t n, struct fnt_params *tparams);
 
 
+MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
+
+
 #endif

+ 24 - 21
mpdecimal/fnt.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2010 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -36,42 +36,45 @@
 #include "fnt.h"
 
 
+/* Bignum: Fast transform for medium-sized coefficients. */
+
+
 /* forward transform, sign = -1 */
 int
 std_fnt(mpd_uint_t *a, mpd_size_t n, int modnum)
 {
-	struct fnt_params *tparams;
+    struct fnt_params *tparams;
 
-	assert(ispower2(n));
-	assert(n >= 4);
-	assert(n <= 3*MPD_MAXTRANSFORM_2N);
+    assert(ispower2(n));
+    assert(n >= 4);
+    assert(n <= 3*MPD_MAXTRANSFORM_2N);
 
-	if ((tparams = _mpd_init_fnt_params(n, -1, modnum)) == NULL) {
-		return 0;
-	}
-	fnt_dif2(a, n, tparams);
+    if ((tparams = _mpd_init_fnt_params(n, -1, modnum)) == NULL) {
+        return 0;
+    }
+    fnt_dif2(a, n, tparams);
 
-	mpd_free(tparams);
-	return 1;
+    mpd_free(tparams);
+    return 1;
 }
 
 /* reverse transform, sign = 1 */
 int
 std_inv_fnt(mpd_uint_t *a, mpd_size_t n, int modnum)
 {
-	struct fnt_params *tparams;
+    struct fnt_params *tparams;
 
-	assert(ispower2(n));
-	assert(n >= 4);
-	assert(n <= 3*MPD_MAXTRANSFORM_2N);
+    assert(ispower2(n));
+    assert(n >= 4);
+    assert(n <= 3*MPD_MAXTRANSFORM_2N);
 
-	if ((tparams = _mpd_init_fnt_params(n, 1, modnum)) == NULL) {
-		return 0;
-	}
-	fnt_dif2(a, n, tparams);
+    if ((tparams = _mpd_init_fnt_params(n, 1, modnum)) == NULL) {
+        return 0;
+    }
+    fnt_dif2(a, n, tparams);
 
-	mpd_free(tparams);
-	return 1;
+    mpd_free(tparams);
+    return 1;
 }
 
 

+ 8 - 1
mpdecimal/fnt.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2010 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -34,9 +34,16 @@
 #include <stdio.h>
 
 
+/* Internal header file: all symbols have local scope in the DSO */
+MPD_PRAGMA(MPD_HIDE_SYMBOLS_START)
+
+
 int std_fnt(mpd_uint_t a[], mpd_size_t n, int modnum);
 int std_inv_fnt(mpd_uint_t a[], mpd_size_t n, int modnum);
 
 
+MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
+
+
 #endif
 

+ 156 - 165
mpdecimal/fourstep.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2010 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -35,14 +35,8 @@
 #include "fourstep.h"
 
 
-/*
- * A variant of the four-step algorithm from:
- *
- * David H. Bailey: FFTs in External or Hierarchical Memory, Journal of
- * Supercomputing, vol. 4, no. 1 (March 1990), p. 23-35.
- *
- * URL: http://crd.lbl.gov/~dhbailey/dhbpapers/
- */
+/* Bignum: Cache efficient Matrix Fourier Transform for arrays of the
+   form 3 * 2**n (See literature/matrix-transform.txt). */
 
 
 #ifndef PPRO
@@ -50,217 +44,214 @@ static inline void
 std_size3_ntt(mpd_uint_t *x1, mpd_uint_t *x2, mpd_uint_t *x3,
               mpd_uint_t w3table[3], mpd_uint_t umod)
 {
-	mpd_uint_t r1, r2;
-	mpd_uint_t w;
-	mpd_uint_t s, tmp;
+    mpd_uint_t r1, r2;
+    mpd_uint_t w;
+    mpd_uint_t s, tmp;
 
 
-	/* k = 0 -> w = 1 */
-	s = *x1;
-	s = addmod(s, *x2, umod);
-	s = addmod(s, *x3, umod);
+    /* k = 0 -> w = 1 */
+    s = *x1;
+    s = addmod(s, *x2, umod);
+    s = addmod(s, *x3, umod);
 
-	r1 = s;
+    r1 = s;
 
-	/* k = 1 */
-	s = *x1;
+    /* k = 1 */
+    s = *x1;
 
-	w = w3table[1];
-	tmp = MULMOD(*x2, w);
-	s = addmod(s, tmp, umod);
+    w = w3table[1];
+    tmp = MULMOD(*x2, w);
+    s = addmod(s, tmp, umod);
 
-	w = w3table[2];
-	tmp = MULMOD(*x3, w);
-	s = addmod(s, tmp, umod);
+    w = w3table[2];
+    tmp = MULMOD(*x3, w);
+    s = addmod(s, tmp, umod);
 
-	r2 = s;
+    r2 = s;
 
-	/* k = 2 */
-	s = *x1;
+    /* k = 2 */
+    s = *x1;
 
-	w = w3table[2];
-	tmp = MULMOD(*x2, w);
-	s = addmod(s, tmp, umod);
+    w = w3table[2];
+    tmp = MULMOD(*x2, w);
+    s = addmod(s, tmp, umod);
 
-	w = w3table[1];
-	tmp = MULMOD(*x3, w);
-	s = addmod(s, tmp, umod);
+    w = w3table[1];
+    tmp = MULMOD(*x3, w);
+    s = addmod(s, tmp, umod);
 
-	*x3 = s;
-	*x2 = r2;
-	*x1 = r1;
+    *x3 = s;
+    *x2 = r2;
+    *x1 = r1;
 }
 #else /* PPRO */
 static inline void
 ppro_size3_ntt(mpd_uint_t *x1, mpd_uint_t *x2, mpd_uint_t *x3, mpd_uint_t w3table[3],
                mpd_uint_t umod, double *dmod, uint32_t dinvmod[3])
 {
-	mpd_uint_t r1, r2;
-	mpd_uint_t w;
-	mpd_uint_t s, tmp;
+    mpd_uint_t r1, r2;
+    mpd_uint_t w;
+    mpd_uint_t s, tmp;
 
 
-	/* k = 0 -> w = 1 */
-	s = *x1;
-	s = addmod(s, *x2, umod);
-	s = addmod(s, *x3, umod);
+    /* k = 0 -> w = 1 */
+    s = *x1;
+    s = addmod(s, *x2, umod);
+    s = addmod(s, *x3, umod);
 
-	r1 = s;
+    r1 = s;
 
-	/* k = 1 */
-	s = *x1;
+    /* k = 1 */
+    s = *x1;
 
-	w = w3table[1];
-	tmp = ppro_mulmod(*x2, w, dmod, dinvmod);
-	s = addmod(s, tmp, umod);
+    w = w3table[1];
+    tmp = ppro_mulmod(*x2, w, dmod, dinvmod);
+    s = addmod(s, tmp, umod);
 
-	w = w3table[2];
-	tmp = ppro_mulmod(*x3, w, dmod, dinvmod);
-	s = addmod(s, tmp, umod);
+    w = w3table[2];
+    tmp = ppro_mulmod(*x3, w, dmod, dinvmod);
+    s = addmod(s, tmp, umod);
 
-	r2 = s;
+    r2 = s;
 
-	/* k = 2 */
-	s = *x1;
+    /* k = 2 */
+    s = *x1;
 
-	w = w3table[2];
-	tmp = ppro_mulmod(*x2, w, dmod, dinvmod);
-	s = addmod(s, tmp, umod);
+    w = w3table[2];
+    tmp = ppro_mulmod(*x2, w, dmod, dinvmod);
+    s = addmod(s, tmp, umod);
 
-	w = w3table[1];
-	tmp = ppro_mulmod(*x3, w, dmod, dinvmod);
-	s = addmod(s, tmp, umod);
+    w = w3table[1];
+    tmp = ppro_mulmod(*x3, w, dmod, dinvmod);
+    s = addmod(s, tmp, umod);
 
-	*x3 = s;
-	*x2 = r2;
-	*x1 = r1;
+    *x3 = s;
+    *x2 = r2;
+    *x1 = r1;
 }
 #endif
 
 
-/* forward transform, sign = -1; transform length = 3 * 2^n */
+/* forward transform, sign = -1; transform length = 3 * 2**n */
 int
 four_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum)
 {
-	mpd_size_t R = 3; /* number of rows */
-	mpd_size_t C = n / 3; /* number of columns */
-	mpd_uint_t w3table[3];
-	mpd_uint_t kernel, w0, w1, wstep;
-	mpd_uint_t *s, *p0, *p1, *p2;
-	mpd_uint_t umod;
+    mpd_size_t R = 3; /* number of rows */
+    mpd_size_t C = n / 3; /* number of columns */
+    mpd_uint_t w3table[3];
+    mpd_uint_t kernel, w0, w1, wstep;
+    mpd_uint_t *s, *p0, *p1, *p2;
+    mpd_uint_t umod;
 #ifdef PPRO
-	double dmod;
-	uint32_t dinvmod[3];
+    double dmod;
+    uint32_t dinvmod[3];
 #endif
-	mpd_size_t i, k;
-
-
-	assert(n >= 48);
-	assert(n <= 3*MPD_MAXTRANSFORM_2N);
-
-
-	SETMODULUS(modnum);
-	_mpd_init_w3table(w3table, -1, modnum);
-	/* size three ntt on the columns */
-	for (p0=a, p1=p0+C, p2=p0+2*C; p0<a+C; p0++,p1++,p2++) {
-
-		SIZE3_NTT(p0, p1, p2, w3table);
-	}
-
-
-	kernel = _mpd_getkernel(n, -1, modnum);
-	for (i = 1; i < R; i++) {
-		w0 = 1;
-		w1 = POWMOD(kernel, i);
-		wstep = MULMOD(w1, w1);
-		for (k = 0; k < C-1; k += 2) {
-			mpd_uint_t x0 = a[i*C+k];
-			mpd_uint_t x1 = a[i*C+k+1];
-			MULMOD2(&x0, w0, &x1, w1);
-			MULMOD2C(&w0, &w1, wstep);
-			a[i*C+k] = x0;
-			a[i*C+k+1] = x1;
-		}
-	}
-
-	/* transform rows */
-	for (s = a; s < a+n; s += C) {
-		if (!six_step_fnt(s, C, modnum)) {
-			return 0;
-		}
-	}
+    mpd_size_t i, k;
+
+
+    assert(n >= 48);
+    assert(n <= 3*MPD_MAXTRANSFORM_2N);
+
+
+    /* Length R transform on the columns. */
+    SETMODULUS(modnum);
+    _mpd_init_w3table(w3table, -1, modnum);
+    for (p0=a, p1=p0+C, p2=p0+2*C; p0<a+C; p0++,p1++,p2++) {
+
+        SIZE3_NTT(p0, p1, p2, w3table);
+    }
+
+    /* Multiply each matrix element (addressed by i*C+k) by r**(i*k). */
+    kernel = _mpd_getkernel(n, -1, modnum);
+    for (i = 1; i < R; i++) {
+        w0 = 1;                  /* r**(i*0): initial value for k=0 */
+        w1 = POWMOD(kernel, i);  /* r**(i*1): initial value for k=1 */
+        wstep = MULMOD(w1, w1);  /* r**(2*i) */
+        for (k = 0; k < C-1; k += 2) {
+            mpd_uint_t x0 = a[i*C+k];
+            mpd_uint_t x1 = a[i*C+k+1];
+            MULMOD2(&x0, w0, &x1, w1);
+            MULMOD2C(&w0, &w1, wstep);  /* r**(i*(k+2)) = r**(i*k) * r**(2*i) */
+            a[i*C+k] = x0;
+            a[i*C+k+1] = x1;
+        }
+    }
+
+    /* Length C transform on the rows. */
+    for (s = a; s < a+n; s += C) {
+        if (!six_step_fnt(s, C, modnum)) {
+            return 0;
+        }
+    }
 
 #if 0
-	/* An unordered transform is sufficient for convolution. */
-	if (ordered) {
-		transpose_3xpow2(a, R, C);
-	}
+    /* An unordered transform is sufficient for convolution. */
+    /* Transpose the matrix. */
+    transpose_3xpow2(a, R, C);
 #endif
 
-	return 1;
+    return 1;
 }
 
-/* backward transform, sign = 1; transform length = 3 * 2^n */
+/* backward transform, sign = 1; transform length = 3 * 2**n */
 int
 inv_four_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum)
 {
-	mpd_size_t R = 3; /* number of rows */
-	mpd_size_t C = n / 3; /* number of columns */
-	mpd_uint_t w3table[3];
-	mpd_uint_t kernel, w0, w1, wstep;
-	mpd_uint_t *s, *p0, *p1, *p2;
-	mpd_uint_t umod;
+    mpd_size_t R = 3; /* number of rows */
+    mpd_size_t C = n / 3; /* number of columns */
+    mpd_uint_t w3table[3];
+    mpd_uint_t kernel, w0, w1, wstep;
+    mpd_uint_t *s, *p0, *p1, *p2;
+    mpd_uint_t umod;
 #ifdef PPRO
-	double dmod;
-	uint32_t dinvmod[3];
+    double dmod;
+    uint32_t dinvmod[3];
 #endif
-	mpd_size_t i, k;
+    mpd_size_t i, k;
 
 
-	assert(n >= 48);
-	assert(n <= 3*MPD_MAXTRANSFORM_2N);
+    assert(n >= 48);
+    assert(n <= 3*MPD_MAXTRANSFORM_2N);
 
 
 #if 0
-	/* An unordered transform is sufficient for convolution. */
-	if (ordered) {
-		transpose_3xpow2(a, C, R);
-	}
+    /* An unordered transform is sufficient for convolution. */
+    /* Transpose the matrix, producing an R*C matrix. */
+    transpose_3xpow2(a, C, R);
 #endif
 
-	/* transform rows */
-	for (s = a; s < a+n; s += C) {
-		if (!inv_six_step_fnt(s, C, modnum)) {
-			return 0;
-		}
-	}
-
-
-	SETMODULUS(modnum);
-	kernel = _mpd_getkernel(n, 1, modnum);
-	for (i = 1; i < R; i++) {
-		w0 = 1;
-		w1 = POWMOD(kernel, i);
-		wstep = MULMOD(w1, w1);
-		for (k = 0; k < C; k += 2) {
-			mpd_uint_t x0 = a[i*C+k];
-			mpd_uint_t x1 = a[i*C+k+1];
-			MULMOD2(&x0, w0, &x1, w1);
-			MULMOD2C(&w0, &w1, wstep);
-			a[i*C+k] = x0;
-			a[i*C+k+1] = x1;
-		}
-	}
-
-
-	_mpd_init_w3table(w3table, 1, modnum);
-	/* size three ntt on the columns */
-	for (p0=a, p1=p0+C, p2=p0+2*C; p0<a+C; p0++,p1++,p2++) {
-
-		SIZE3_NTT(p0, p1, p2, w3table);
-	}
-
-	return 1;
+    /* Length C transform on the rows. */
+    for (s = a; s < a+n; s += C) {
+        if (!inv_six_step_fnt(s, C, modnum)) {
+            return 0;
+        }
+    }
+
+    /* Multiply each matrix element (addressed by i*C+k) by r**(i*k). */
+    SETMODULUS(modnum);
+    kernel = _mpd_getkernel(n, 1, modnum);
+    for (i = 1; i < R; i++) {
+        w0 = 1;
+        w1 = POWMOD(kernel, i);
+        wstep = MULMOD(w1, w1);
+        for (k = 0; k < C; k += 2) {
+            mpd_uint_t x0 = a[i*C+k];
+            mpd_uint_t x1 = a[i*C+k+1];
+            MULMOD2(&x0, w0, &x1, w1);
+            MULMOD2C(&w0, &w1, wstep);
+            a[i*C+k] = x0;
+            a[i*C+k+1] = x1;
+        }
+    }
+
+    /* Length R transform on the columns. */
+    _mpd_init_w3table(w3table, 1, modnum);
+    for (p0=a, p1=p0+C, p2=p0+2*C; p0<a+C; p0++,p1++,p2++) {
+
+        SIZE3_NTT(p0, p1, p2, w3table);
+    }
+
+    return 1;
 }
 
 

+ 8 - 1
mpdecimal/fourstep.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2010 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -34,8 +34,15 @@
 #include <stdio.h>
 
 
+/* Internal header file: all symbols have local scope in the DSO */
+MPD_PRAGMA(MPD_HIDE_SYMBOLS_START)
+
+
 int four_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum);
 int inv_four_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum);
 
 
+MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
+
+
 #endif

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 730 - 656
mpdecimal/io.c


+ 13 - 13
mpdecimal/io.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2010 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -41,18 +41,18 @@
 static inline mpd_ssize_t
 mpd_strtossize(const char *s, char **end, int base)
 {
-	int64_t retval;
-
-	errno = 0;
-	retval = _mpd_strtossize(s, end, base);
-	if (errno == 0 && (retval > MPD_SSIZE_MAX || retval < MPD_SSIZE_MIN)) {
-		errno = ERANGE;
-	}
-	if (errno == ERANGE) {
-		return (retval < 0) ? MPD_SSIZE_MIN : MPD_SSIZE_MAX;
-	}
-
-	return (mpd_ssize_t)retval;
+    int64_t retval;
+
+    errno = 0;
+    retval = _mpd_strtossize(s, end, base);
+    if (errno == 0 && (retval > MPD_SSIZE_MAX || retval < MPD_SSIZE_MIN)) {
+        errno = ERANGE;
+    }
+    if (errno == ERANGE) {
+        return (retval < 0) ? MPD_SSIZE_MIN : MPD_SSIZE_MAX;
+    }
+
+    return (mpd_ssize_t)retval;
 }
 #endif
 

+ 176 - 123
mpdecimal/memory.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2010 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -33,35 +33,46 @@
 #include "memory.h"
 
 
+/* Guaranteed minimum allocation for a coefficient. May be changed once
+   at program start using mpd_setminalloc(). */
 mpd_ssize_t MPD_MINALLOC = MPD_MINALLOC_MIN;
 
+/* Custom allocation and free functions */
 void *(* mpd_mallocfunc)(size_t size) = malloc;
 void *(* mpd_reallocfunc)(void *ptr, size_t size) = realloc;
 void *(* mpd_callocfunc)(size_t nmemb, size_t size) = calloc;
 void (* mpd_free)(void *ptr) = free;
 
 
-
 /* emulate calloc if it is not available */
 void *
 mpd_callocfunc_em(size_t nmemb, size_t size)
 {
-	void *ptr;
-	size_t req;
+    void *ptr;
+    size_t req;
+    mpd_size_t overflow;
 
 #if MPD_SIZE_MAX < SIZE_MAX
-	if (nmemb > MPD_SIZE_MAX || size > MPD_SIZE_MAX) {
-		return NULL;
-	}
+    /* full_coverage test only */
+    if (nmemb > MPD_SIZE_MAX || size > MPD_SIZE_MAX) {
+        return NULL;
+    }
 #endif
-	req = mul_size_t((mpd_size_t)nmemb, (mpd_size_t)size);
-	if ((ptr = mpd_mallocfunc(req)) == NULL) {
-		return NULL;
-	}
-	/* used on uint32_t or uint64_t */
-	memset(ptr, 0, req);
-
-	return ptr;
+
+    req = mul_size_t_overflow((mpd_size_t)nmemb, (mpd_size_t)size,
+                              &overflow);
+    if (overflow) {
+        return NULL;
+    }
+
+    ptr = mpd_mallocfunc(req);
+    if (ptr == NULL) {
+        return NULL;
+    }
+    /* used on uint32_t or uint64_t */
+    memset(ptr, 0, req);
+
+    return ptr;
 }
 
 
@@ -69,171 +80,213 @@ mpd_callocfunc_em(size_t nmemb, size_t size)
 void *
 mpd_alloc(mpd_size_t nmemb, mpd_size_t size)
 {
-	void *ptr;
-	mpd_size_t req;
+    mpd_size_t req, overflow;
 
-	req = mul_size_t(nmemb, size);
-	if ((ptr = mpd_mallocfunc(req)) == NULL) {
-		return NULL;
-	}
+    req = mul_size_t_overflow(nmemb, size, &overflow);
+    if (overflow) {
+        return NULL;
+    }
 
-	return ptr;
+    return mpd_mallocfunc(req);
 }
 
 /* calloc with overflow checking */
 void *
 mpd_calloc(mpd_size_t nmemb, mpd_size_t size)
 {
-	void *ptr;
+    mpd_size_t overflow;
 
-	if ((ptr = mpd_callocfunc(nmemb, size)) == NULL) {
-		return NULL;
-	}
+    (void)mul_size_t_overflow(nmemb, size, &overflow);
+    if (overflow) {
+        return NULL;
+    }
 
-	return ptr;
+    return mpd_callocfunc(nmemb, size);
 }
 
 /* realloc with overflow checking */
 void *
 mpd_realloc(void *ptr, mpd_size_t nmemb, mpd_size_t size, uint8_t *err)
 {
-	void *new;
-	mpd_size_t req;
-
-	req = mul_size_t(nmemb, size);
-	if ((new = mpd_reallocfunc(ptr, req)) == NULL) {
-		*err = 1;
-		return ptr;
-	}
-
-	return new;
+    void *new;
+    mpd_size_t req, overflow;
+
+    req = mul_size_t_overflow(nmemb, size, &overflow);
+    if (overflow) {
+        *err = 1;
+        return ptr;
+    }
+
+    new = mpd_reallocfunc(ptr, req);
+    if (new == NULL) {
+        *err = 1;
+        return ptr;
+    }
+
+    return new;
 }
 
 /* struct hack malloc with overflow checking */
 void *
 mpd_sh_alloc(mpd_size_t struct_size, mpd_size_t nmemb, mpd_size_t size)
 {
-	void *ptr;
-	mpd_size_t req;
+    mpd_size_t req, overflow;
 
-	req = mul_size_t(nmemb, size);
-	req = add_size_t(req, struct_size);
-	if ((ptr = mpd_mallocfunc(req)) == NULL) {
-		return NULL;
-	}
+    req = mul_size_t_overflow(nmemb, size, &overflow);
+    if (overflow) {
+        return NULL;
+    }
 
-	return ptr;
+    req = add_size_t_overflow(req, struct_size, &overflow);
+    if (overflow) {
+        return NULL;
+    }
+
+    return mpd_mallocfunc(req);
 }
 
 
-/* Allocate a new decimal with data-size 'size'.
- * In case of an error the return value is NULL.
- */
+/* Allocate a new decimal with a coefficient of length 'nwords'. In case
+   of an error the return value is NULL. */
 mpd_t *
-mpd_qnew_size(mpd_ssize_t size)
+mpd_qnew_size(mpd_ssize_t nwords)
 {
-	mpd_t *result;
+    mpd_t *result;
+
+    nwords = (nwords < MPD_MINALLOC) ? MPD_MINALLOC : nwords;
 
-	size = (size < MPD_MINALLOC) ? MPD_MINALLOC : size;
+    result = mpd_alloc(1, sizeof *result);
+    if (result == NULL) {
+        return NULL;
+    }
 
-	if ((result = mpd_alloc(1, sizeof *result)) == NULL) {
-		return NULL;
-	}
-	if ((result->data = mpd_alloc(size, sizeof *result->data)) == NULL) {
-		mpd_free(result);
-		return NULL;
-	}
+    result->data = mpd_alloc(nwords, sizeof *result->data);
+    if (result->data == NULL) {
+        mpd_free(result);
+        return NULL;
+    }
 
-	result->flags = 0;
-	result->exp = 0;
-	result->digits = 0;
-	result->len = 0;
-	result->alloc = size;
+    result->flags = 0;
+    result->exp = 0;
+    result->digits = 0;
+    result->len = 0;
+    result->alloc = nwords;
 
-	return result;
+    return result;
 }
 
-/* Allocate a new decimal with data-size MPD_MINALLOC.
- * In case of an error the return value is NULL.
- */
+/* Allocate a new decimal with a coefficient of length MPD_MINALLOC.
+   In case of an error the return value is NULL. */
 mpd_t *
 mpd_qnew(void)
 {
-	return mpd_qnew_size(MPD_MINALLOC);
+    return mpd_qnew_size(MPD_MINALLOC);
 }
 
 /* Allocate new decimal. Caller can check for NULL or MPD_Malloc_error.
- * Raises on error.
- */
+   Raises on error. */
 mpd_t *
 mpd_new(mpd_context_t *ctx)
 {
-	mpd_t *result;
+    mpd_t *result;
 
-	if ((result = mpd_qnew()) == NULL) {
-		mpd_addstatus_raise(ctx, MPD_Malloc_error);
-	}
-	return result;
+    result = mpd_qnew();
+    if (result == NULL) {
+        mpd_addstatus_raise(ctx, MPD_Malloc_error);
+    }
+    return result;
 }
 
+/*
+ * Input: 'result' is a static mpd_t with a static coefficient.
+ * Assumption: 'nwords' >= result->alloc.
+ *
+ * Resize the static coefficient to a larger dynamic one and copy the
+ * existing data. If successful, the value of 'result' is unchanged.
+ * Otherwise, set 'result' to NaN and update 'status' with MPD_Malloc_error.
+ */
 int
-mpd_switch_to_dyn(mpd_t *result, mpd_ssize_t size, uint32_t *status)
+mpd_switch_to_dyn(mpd_t *result, mpd_ssize_t nwords, uint32_t *status)
 {
-	mpd_uint_t *p = result->data;
-
-	if ((result->data = mpd_alloc(size, sizeof *result->data)) == NULL) {
-		result->data = p;
-		mpd_set_qnan(result);
-		mpd_set_positive(result);
-		result->exp = result->digits = result->len = 0;
-		*status |= MPD_Malloc_error;
-		return 0;
-	}
-
-	memcpy(result->data, p, result->len * (sizeof *result->data));
-	result->alloc = size;
-	mpd_set_dynamic_data(result);
-	return 1;
+    mpd_uint_t *p = result->data;
+
+    assert(nwords >= result->alloc);
+
+    result->data = mpd_alloc(nwords, sizeof *result->data);
+    if (result->data == NULL) {
+        result->data = p;
+        mpd_set_qnan(result);
+        mpd_set_positive(result);
+        result->exp = result->digits = result->len = 0;
+        *status |= MPD_Malloc_error;
+        return 0;
+    }
+
+    memcpy(result->data, p, result->alloc * (sizeof *result->data));
+    result->alloc = nwords;
+    mpd_set_dynamic_data(result);
+    return 1;
 }
 
+/*
+ * Input: 'result' is a static mpd_t with a static coefficient.
+ *
+ * Convert the coefficient to a dynamic one that is initialized to zero. If
+ * malloc fails, set 'result' to NaN and update 'status' with MPD_Malloc_error.
+ */
 int
-mpd_switch_to_dyn_zero(mpd_t *result, mpd_ssize_t size, uint32_t *status)
+mpd_switch_to_dyn_zero(mpd_t *result, mpd_ssize_t nwords, uint32_t *status)
 {
-	mpd_uint_t *p = result->data;
-
-	if ((result->data = mpd_calloc(size, sizeof *result->data)) == NULL) {
-		result->data = p;
-		mpd_set_qnan(result);
-		mpd_set_positive(result);
-		result->exp = result->digits = result->len = 0;
-		*status |= MPD_Malloc_error;
-		return 0;
-	}
-
-	result->alloc = size;
-	mpd_set_dynamic_data(result);
-
-	return 1;
+    mpd_uint_t *p = result->data;
+
+    result->data = mpd_calloc(nwords, sizeof *result->data);
+    if (result->data == NULL) {
+        result->data = p;
+        mpd_set_qnan(result);
+        mpd_set_positive(result);
+        result->exp = result->digits = result->len = 0;
+        *status |= MPD_Malloc_error;
+        return 0;
+    }
+
+    result->alloc = nwords;
+    mpd_set_dynamic_data(result);
+
+    return 1;
 }
 
+/*
+ * Input: 'result' is a static or a dynamic mpd_t with a dynamic coefficient.
+ * Resize the coefficient to length 'nwords':
+ *   Case nwords > result->alloc:
+ *     If realloc is successful:
+ *       'result' has a larger coefficient but the same value. Return 1.
+ *     Otherwise:
+ *       Set 'result' to NaN, update status with MPD_Malloc_error and return 0.
+ *   Case nwords < result->alloc:
+ *     If realloc is successful:
+ *       'result' has a smaller coefficient. result->len is undefined. Return 1.
+ *     Otherwise (unlikely):
+ *       'result' is unchanged. Reuse the now oversized coefficient. Return 1.
+ */
 int
-mpd_realloc_dyn(mpd_t *result, mpd_ssize_t size, uint32_t *status)
+mpd_realloc_dyn(mpd_t *result, mpd_ssize_t nwords, uint32_t *status)
 {
-	uint8_t err = 0;
-
-	result->data = mpd_realloc(result->data, size, sizeof *result->data, &err);
-	if (!err) {
-		result->alloc = size;
-	}
-	else if (size > result->alloc) {
-		mpd_set_qnan(result);
-		mpd_set_positive(result);
-		result->exp = result->digits = result->len = 0;
-		*status |= MPD_Malloc_error;
-		return 0;
-	}
-
-	return 1;
+    uint8_t err = 0;
+
+    result->data = mpd_realloc(result->data, nwords, sizeof *result->data, &err);
+    if (!err) {
+        result->alloc = nwords;
+    }
+    else if (nwords > result->alloc) {
+        mpd_set_qnan(result);
+        mpd_set_positive(result);
+        result->exp = result->digits = result->len = 0;
+        *status |= MPD_Malloc_error;
+        return 0;
+    }
+
+    return 1;
 }
 
 

+ 8 - 1
mpdecimal/memory.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2010 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -33,11 +33,18 @@
 #include "mpdecimal.h"
 
 
+/* Internal header file: all symbols have local scope in the DSO */
+MPD_PRAGMA(MPD_HIDE_SYMBOLS_START)
+
+
 int mpd_switch_to_dyn(mpd_t *result, mpd_ssize_t size, uint32_t *status);
 int mpd_switch_to_dyn_zero(mpd_t *result, mpd_ssize_t size, uint32_t *status);
 int mpd_realloc_dyn(mpd_t *result, mpd_ssize_t size, uint32_t *status);
 
 
+MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
+
+
 #endif
 
 

+ 751 - 0
mpdecimal/mpdecimal.32.h

@@ -0,0 +1,751 @@
+/*
+ * Copyright (c) 2008-2010 Stefan Krah. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#ifndef MPDECIMAL_32_H
+#define MPDECIMAL_32_H
+
+
+#ifdef __cplusplus
+extern "C" {
+#define __STDC_LIMIT_MACROS
+#endif
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <assert.h>
+#include <stdint.h>
+
+
+#if !defined(__GNUC_STDC_INLINE__)
+  #define __GNUC_STDC_INLINE__
+#endif
+#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
+  #define UNUSED __attribute__((unused))
+#else
+  #define UNUSED
+#endif
+
+
+/******************************************************************************/
+/*                              Configuration                                 */
+/******************************************************************************/
+
+/* ABI: 32-bit */
+#ifdef CONFIG_64
+  #error "cannot use CONFIG_64 with 32-bit header."
+#endif
+
+#ifndef CONFIG_32
+  #define CONFIG_32
+#endif
+
+
+/* BEGIN CONFIG_64 */
+#if defined(CONFIG_64)
+/* types for modular and base arithmetic */
+#define MPD_UINT_MAX UINT64_MAX
+#define MPD_BITS_PER_UINT 64
+typedef uint64_t mpd_uint_t;  /* unsigned mod type */
+
+#define MPD_SIZE_MAX SIZE_MAX
+typedef size_t mpd_size_t; /* unsigned size type */
+
+/* type for exp, digits, len, prec */
+#define MPD_SSIZE_MAX INT64_MAX
+#define MPD_SSIZE_MIN INT64_MIN
+typedef int64_t mpd_ssize_t;
+#define _mpd_strtossize strtoll
+
+/* decimal arithmetic */
+#define MPD_RADIX 10000000000000000000ULL  /* 10**19 */
+#define MPD_RDIGITS 19
+#define MPD_MAX_POW10 19
+#define MPD_EXPDIGITS 19  /* MPD_EXPDIGITS <= MPD_RDIGITS+1 */
+
+#define MPD_MAXTRANSFORM_2N 4294967296ULL      /* 2**32 */
+#define MPD_MAX_PREC 999999999999999999LL
+#define MPD_MAX_PREC_LOG2 64
+#define MPD_ELIMIT  1000000000000000000LL
+#define MPD_MAX_EMAX   999999999999999999LL    /* ELIMIT-1 */
+#define MPD_MIN_EMIN  (-999999999999999999LL)  /* -EMAX */
+#define MPD_MIN_ETINY (MPD_MIN_EMIN-(MPD_MAX_PREC-1))
+#define MPD_EXP_INF 2000000000000000001LL
+#define MPD_EXP_CLAMP (-4000000000000000001LL)
+#define MPD_MAXIMPORT 105263157894736842L /* ceil((2*MPD_MAX_PREC)/MPD_RDIGITS) */
+/* END CONFIG_64 */
+
+
+/* BEGIN CONFIG_32 */
+#elif defined(CONFIG_32)
+/* types for modular and base arithmetic */
+#define MPD_UINT_MAX UINT32_MAX
+#define MPD_BITS_PER_UINT 32
+typedef uint32_t mpd_uint_t;  /* unsigned mod type */
+
+#ifndef LEGACY_COMPILER
+#define MPD_UUINT_MAX UINT64_MAX
+typedef uint64_t mpd_uuint_t; /* double width unsigned mod type */
+#endif
+
+#define MPD_SIZE_MAX SIZE_MAX
+typedef size_t mpd_size_t; /* unsigned size type */
+
+/* type for dec->len, dec->exp, ctx->prec */
+#define MPD_SSIZE_MAX INT32_MAX
+#define MPD_SSIZE_MIN INT32_MIN
+typedef int32_t mpd_ssize_t;
+#define _mpd_strtossize strtol
+
+/* decimal arithmetic */
+#define MPD_RADIX 1000000000UL  /* 10**9 */
+#define MPD_RDIGITS 9
+#define MPD_MAX_POW10 9
+#define MPD_EXPDIGITS 10 /* MPD_EXPDIGITS <= MPD_RDIGITS+1 */
+
+#define MPD_MAXTRANSFORM_2N 33554432UL /* 2**25 */
+#define MPD_MAX_PREC 425000000L
+#define MPD_MAX_PREC_LOG2 32
+#define MPD_ELIMIT 425000001L
+#define MPD_MAX_EMAX 425000000L        /* ELIMIT-1 */
+#define MPD_MIN_EMIN (-425000000L)     /* -EMAX */
+#define MPD_MIN_ETINY (MPD_MIN_EMIN-(MPD_MAX_PREC-1))
+#define MPD_EXP_INF 1000000001L      /* allows for emax=999999999 in the tests */
+#define MPD_EXP_CLAMP (-2000000001L) /* allows for emin=-999999999 in the tests */
+#define MPD_MAXIMPORT 94444445L      /* ceil((2*MPD_MAX_PREC)/MPD_RDIGITS) */
+/* END CONFIG_32 */
+
+#else
+  #error "define CONFIG_64 or CONFIG_32"
+#endif
+/* END CONFIG */
+
+
+#if MPD_SIZE_MAX != MPD_UINT_MAX
+  #error "unsupported platform: need mpd_size_t == mpd_uint_t"
+#endif
+
+
+/******************************************************************************/
+/*                                Context                                     */
+/******************************************************************************/
+
+enum {
+	MPD_ROUND_UP,          /* round away from 0               */
+	MPD_ROUND_DOWN,        /* round toward 0 (truncate)       */
+	MPD_ROUND_CEILING,     /* round toward +infinity          */
+	MPD_ROUND_FLOOR,       /* round toward -infinity          */
+	MPD_ROUND_HALF_UP,     /* 0.5 is rounded up               */
+	MPD_ROUND_HALF_DOWN,   /* 0.5 is rounded down             */
+	MPD_ROUND_HALF_EVEN,   /* 0.5 is rounded to even          */
+	MPD_ROUND_05UP,        /* round zero or five away from 0  */
+	MPD_ROUND_TRUNC,       /* truncate, but set infinity      */
+	MPD_ROUND_GUARD
+};
+
+enum { MPD_CLAMP_DEFAULT, MPD_CLAMP_IEEE_754, MPD_CLAMP_GUARD };
+
+extern const char *mpd_round_string[MPD_ROUND_GUARD];
+extern const char *mpd_clamp_string[MPD_CLAMP_GUARD];
+
+
+typedef struct {
+	mpd_ssize_t prec;   /* precision */
+	mpd_ssize_t emax;   /* max positive exp */
+	mpd_ssize_t emin;   /* min negative exp */
+	uint32_t traps;     /* status events that should be trapped */
+	uint32_t status;    /* status flags */
+	uint32_t newtrap;   /* set by mpd_addstatus_raise() */
+	int      round;     /* rounding mode */
+	int      clamp;     /* clamp mode */
+	int      allcr;     /* all functions correctly rounded */
+} mpd_context_t;
+
+
+/* Status flags */
+#define MPD_Clamped             0x00000001U
+#define MPD_Conversion_syntax   0x00000002U
+#define MPD_Division_by_zero    0x00000004U
+#define MPD_Division_impossible 0x00000008U
+#define MPD_Division_undefined  0x00000010U
+#define MPD_Fpu_error           0x00000020U
+#define MPD_Inexact             0x00000040U
+#define MPD_Invalid_context     0x00000080U
+#define MPD_Invalid_operation   0x00000100U
+#define MPD_Malloc_error        0x00000200U
+#define MPD_Not_implemented     0x00000400U
+#define MPD_Overflow            0x00000800U
+#define MPD_Rounded             0x00001000U
+#define MPD_Subnormal           0x00002000U
+#define MPD_Underflow           0x00004000U
+#define MPD_Max_status         (0x00008000U-1U)
+
+/* Conditions that result in an IEEE 754 exception */
+#define MPD_IEEE_Invalid_operation (MPD_Conversion_syntax |   \
+                                    MPD_Division_impossible | \
+                                    MPD_Division_undefined |  \
+                                    MPD_Fpu_error |           \
+                                    MPD_Invalid_context |     \
+                                    MPD_Invalid_operation |   \
+                                    MPD_Malloc_error)         \
+
+/* Errors that require the result of an operation to be set to NaN */
+#define MPD_Errors (MPD_IEEE_Invalid_operation | \
+                    MPD_Division_by_zero)
+
+/* Default traps */
+#define MPD_Traps (MPD_IEEE_Invalid_operation | \
+                   MPD_Division_by_zero |       \
+                   MPD_Overflow |               \
+                   MPD_Underflow)
+
+/* Official name */
+#define MPD_Insufficient_storage MPD_Malloc_error
+
+/* IEEE 754 interchange format contexts */
+#define MPD_IEEE_CONTEXT_MAX_BITS 512 /* 16*(log2(MPD_MAX_EMAX / 3)-3) */
+#define MPD_DECIMAL32 32
+#define MPD_DECIMAL64 64
+#define MPD_DECIMAL128 128
+
+
+#define MPD_MINALLOC_MIN 2
+#define MPD_MINALLOC_MAX 64
+extern mpd_ssize_t MPD_MINALLOC;
+extern void (* mpd_traphandler)(mpd_context_t *);
+void mpd_dflt_traphandler(mpd_context_t *);
+
+void mpd_setminalloc(mpd_ssize_t n);
+void mpd_init(mpd_context_t *ctx, mpd_ssize_t prec);
+
+void mpd_maxcontext(mpd_context_t *ctx);
+void mpd_maxcontext_plus(mpd_context_t *workctx, const mpd_context_t *ctx);
+void mpd_defaultcontext(mpd_context_t *ctx);
+void mpd_basiccontext(mpd_context_t *ctx);
+int mpd_ieee_context(mpd_context_t *ctx, int bits);
+
+mpd_ssize_t mpd_getprec(const mpd_context_t *ctx);
+mpd_ssize_t mpd_getemax(const mpd_context_t *ctx);
+mpd_ssize_t mpd_getemin(const mpd_context_t *ctx);
+int mpd_getround(const mpd_context_t *ctx);
+uint32_t mpd_gettraps(const mpd_context_t *ctx);
+uint32_t mpd_getstatus(const mpd_context_t *ctx);
+int mpd_getclamp(const mpd_context_t *ctx);
+int mpd_getcr(const mpd_context_t *ctx);
+
+int mpd_qsetprec(mpd_context_t *ctx, mpd_ssize_t prec);
+int mpd_qsetemax(mpd_context_t *ctx, mpd_ssize_t emax);
+int mpd_qsetemin(mpd_context_t *ctx, mpd_ssize_t emin);
+int mpd_qsetround(mpd_context_t *ctx, int newround);
+int mpd_qsettraps(mpd_context_t *ctx, uint32_t flags);
+int mpd_qsetstatus(mpd_context_t *ctx, uint32_t flags);
+int mpd_qsetclamp(mpd_context_t *ctx, int c);
+int mpd_qsetcr(mpd_context_t *ctx, int c);
+void mpd_addstatus_raise(mpd_context_t *ctx, uint32_t flags);
+
+
+/******************************************************************************/
+/*                           Decimal Arithmetic                               */
+/******************************************************************************/
+
+/* mpd_t flags */
+#define MPD_POS                 ((uint8_t)0)
+#define MPD_NEG                 ((uint8_t)1)
+#define MPD_INF                 ((uint8_t)2)
+#define MPD_NAN                 ((uint8_t)4)
+#define MPD_SNAN                ((uint8_t)8)
+#define MPD_SPECIAL (MPD_INF|MPD_NAN|MPD_SNAN)
+#define MPD_STATIC              ((uint8_t)16)
+#define MPD_STATIC_DATA         ((uint8_t)32)
+#define MPD_SHARED_DATA         ((uint8_t)64)
+#define MPD_CONST_DATA          ((uint8_t)128)
+#define MPD_DATAFLAGS (MPD_STATIC_DATA|MPD_SHARED_DATA|MPD_CONST_DATA)
+
+/* mpd_t */
+typedef struct {
+	uint8_t flags;
+	mpd_ssize_t exp;
+	mpd_ssize_t digits;
+	mpd_ssize_t len;
+	mpd_ssize_t alloc;
+	mpd_uint_t *data;
+} mpd_t;
+
+
+typedef unsigned char uchar;
+extern mpd_t mpd_ln10;
+
+
+/******************************************************************************/
+/*                       Quiet, thread-safe functions                         */
+/******************************************************************************/
+
+/* format specification */
+typedef struct {
+	mpd_ssize_t min_width; /* minimum field width */
+	mpd_ssize_t prec;      /* fraction digits or significant digits */
+	char type;             /* conversion specifier */
+	char align;            /* alignment */
+	char sign;             /* sign printing/alignment */
+	char fill[5];          /* fill character */
+	const char *dot;       /* decimal point */
+	const char *sep;       /* thousands separator */
+	const char *grouping;  /* grouping of digits */
+} mpd_spec_t;
+
+/* output to a string */
+char *mpd_to_sci(const mpd_t *dec, int fmt);
+char *mpd_to_eng(const mpd_t *dec, int fmt);
+int mpd_parse_fmt_str(mpd_spec_t *spec, const char *fmt, int caps);
+char * mpd_qformat_spec(const mpd_t *dec, mpd_spec_t *spec, const mpd_context_t *ctx, uint32_t *status);
+char *mpd_qformat(const mpd_t *dec, const char *fmt, const mpd_context_t *ctx, uint32_t *status);
+
+#define MPD_NUM_FLAGS 15
+#define MPD_MAX_FLAG_STRING 208
+#define MPD_MAX_FLAG_LIST (MPD_MAX_FLAG_STRING+18)
+#define MPD_MAX_SIGNAL_LIST 121
+int mpd_snprint_flags(char *dest, int nmemb, uint32_t flags);
+int mpd_lsnprint_flags(char *dest, int nmemb, uint32_t flags, const char *flag_string[]);
+int mpd_lsnprint_signals(char *dest, int nmemb, uint32_t flags, const char *signal_string[]);
+
+/* output to a file */
+void mpd_fprint(FILE *file, const mpd_t *dec);
+void mpd_print(const mpd_t *dec);
+
+/* assignment from a string */
+void mpd_qset_string(mpd_t *dec, const char *s, const mpd_context_t *ctx, uint32_t *status);
+
+/* set to NaN with error flags */
+void mpd_seterror(mpd_t *result, uint32_t flags, uint32_t *status);
+/* set a special with sign and type */
+void mpd_setspecial(mpd_t *dec, uint8_t sign, uint8_t type);
+/* set coefficient to zero or all nines */
+void mpd_zerocoeff(mpd_t *result);
+void mpd_qmaxcoeff(mpd_t *result, const mpd_context_t *ctx, uint32_t *status);
+
+/* quietly assign a C integer type to an mpd_t */
+void mpd_qset_ssize(mpd_t *result, mpd_ssize_t a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qset_i32(mpd_t *result, int32_t a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qset_uint(mpd_t *result, mpd_uint_t a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qset_u32(mpd_t *result, uint32_t a, const mpd_context_t *ctx, uint32_t *status);
+#ifndef LEGACY_COMPILER
+void mpd_qset_i64(mpd_t *result, int64_t a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qset_u64(mpd_t *result, uint64_t a, const mpd_context_t *ctx, uint32_t *status);
+#endif
+
+/* quietly assign a C integer type to an mpd_t with a static coefficient */
+void mpd_qsset_ssize(mpd_t *result, mpd_ssize_t a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qsset_i32(mpd_t *result, int32_t a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qsset_uint(mpd_t *result, mpd_uint_t a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qsset_u32(mpd_t *result, uint32_t a, const mpd_context_t *ctx, uint32_t *status);
+
+/* quietly get a C integer type from an mpd_t */
+mpd_ssize_t mpd_qget_ssize(const mpd_t *dec, uint32_t *status);
+mpd_uint_t mpd_qget_uint(const mpd_t *dec, uint32_t *status);
+mpd_uint_t mpd_qabs_uint(const mpd_t *dec, uint32_t *status);
+
+
+/* quiet functions */
+int mpd_qcheck_nan(mpd_t *nanresult, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+int mpd_qcheck_nans(mpd_t *nanresult, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qfinalize(mpd_t *result, const mpd_context_t *ctx, uint32_t *status);
+
+const char * mpd_class(const mpd_t *a, const mpd_context_t *ctx);
+
+int mpd_qcopy(mpd_t *result, const mpd_t *a,  uint32_t *status);
+mpd_t *mpd_qncopy(const mpd_t *a);
+int mpd_qcopy_abs(mpd_t *result, const mpd_t *a, uint32_t *status);
+int mpd_qcopy_negate(mpd_t *result, const mpd_t *a, uint32_t *status);
+int mpd_qcopy_sign(mpd_t *result, const mpd_t *a, const mpd_t *b, uint32_t *status);
+
+void mpd_qand(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qinvert(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qlogb(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qor(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qscaleb(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qxor(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+int mpd_same_quantum(const mpd_t *a, const mpd_t *b);
+
+void mpd_qrotate(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+int mpd_qshiftl(mpd_t *result, const mpd_t *a, mpd_ssize_t n, uint32_t *status);
+mpd_uint_t mpd_qshiftr(mpd_t *result, const mpd_t *a, mpd_ssize_t n, uint32_t *status);
+mpd_uint_t mpd_qshiftr_inplace(mpd_t *result, mpd_ssize_t n);
+void mpd_qshift(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qshiftn(mpd_t *result, const mpd_t *a, mpd_ssize_t n, const mpd_context_t *ctx, uint32_t *status);
+
+int mpd_qcmp(const mpd_t *a, const mpd_t *b, uint32_t *status);
+int mpd_qcompare(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+int mpd_qcompare_signal(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+int mpd_cmp_total(const mpd_t *a, const mpd_t *b);
+int mpd_cmp_total_mag(const mpd_t *a, const mpd_t *b);
+int mpd_compare_total(mpd_t *result, const mpd_t *a, const mpd_t *b);
+int mpd_compare_total_mag(mpd_t *result, const mpd_t *a, const mpd_t *b);
+
+void mpd_qround_to_intx(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qround_to_int(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qtrunc(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qfloor(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qceil(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+
+void mpd_qabs(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qmax(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qmax_mag(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qmin(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qmin_mag(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qminus(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qplus(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qnext_minus(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qnext_plus(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qnext_toward(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qquantize(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qrescale(mpd_t *result, const mpd_t *a, mpd_ssize_t exp, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qreduce(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qadd(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qadd_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qadd_i32(mpd_t *result, const mpd_t *a, int32_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qadd_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qadd_u32(mpd_t *result, const mpd_t *a, uint32_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qsub(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qsub_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qsub_i32(mpd_t *result, const mpd_t *a, int32_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qsub_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qsub_u32(mpd_t *result, const mpd_t *a, uint32_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qmul(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qmul_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qmul_i32(mpd_t *result, const mpd_t *a, int32_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qmul_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qmul_u32(mpd_t *result, const mpd_t *a, uint32_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qfma(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_t *c, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qdiv(mpd_t *q, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qdiv_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qdiv_i32(mpd_t *result, const mpd_t *a, int32_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qdiv_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qdiv_u32(mpd_t *result, const mpd_t *a, uint32_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qdivint(mpd_t *q, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qrem(mpd_t *r, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qrem_near(mpd_t *r, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qdivmod(mpd_t *q, mpd_t *r, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qpow(mpd_t *result, const mpd_t *base, const mpd_t *exp, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qpowmod(mpd_t *result, const mpd_t *base, const mpd_t *exp, const mpd_t *mod, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qexp(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_update_ln10(mpd_ssize_t prec, uint32_t *status);
+void mpd_qln(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qlog10(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qsqrt(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qinvroot(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+
+
+size_t mpd_sizeinbase(mpd_t *a, uint32_t base);
+void mpd_qimport_u16(mpd_t *result, const uint16_t *srcdata, size_t srclen,
+                     uint8_t srcsign, uint32_t srcbase,
+                     const mpd_context_t *ctx, uint32_t *status);
+void mpd_qimport_u32(mpd_t *result, const uint32_t *srcdata, size_t srclen,
+                     uint8_t srcsign, uint32_t srcbase,
+                     const mpd_context_t *ctx, uint32_t *status);
+size_t mpd_qexport_u16(uint16_t *rdata, size_t rlen, uint32_t base,
+                       const mpd_t *src, uint32_t *status);
+size_t mpd_qexport_u32(uint32_t *rdata, size_t rlen, uint32_t base,
+                       const mpd_t *src, uint32_t *status);
+
+
+/******************************************************************************/
+/*                           Signalling functions                             */
+/******************************************************************************/
+
+char * mpd_format(const mpd_t *dec, const char *fmt, mpd_context_t *ctx);
+void mpd_import_u16(mpd_t *result, const uint16_t *srcdata, size_t srclen, uint8_t srcsign, uint32_t base, mpd_context_t *ctx);
+void mpd_import_u32(mpd_t *result, const uint32_t *srcdata, size_t srclen, uint8_t srcsign, uint32_t base, mpd_context_t *ctx);
+size_t mpd_export_u16(uint16_t *rdata, size_t rlen, uint32_t base, const mpd_t *src, mpd_context_t *ctx);
+size_t mpd_export_u32(uint32_t *rdata, size_t rlen, uint32_t base, const mpd_t *src, mpd_context_t *ctx);
+void mpd_finalize(mpd_t *result, mpd_context_t *ctx);
+int mpd_check_nan(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+int mpd_check_nans(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_set_string(mpd_t *result, const char *s, mpd_context_t *ctx);
+void mpd_maxcoeff(mpd_t *result, mpd_context_t *ctx);
+void mpd_sset_ssize(mpd_t *result, mpd_ssize_t a, mpd_context_t *ctx);
+void mpd_sset_i32(mpd_t *result, int32_t a, mpd_context_t *ctx);
+void mpd_sset_uint(mpd_t *result, mpd_uint_t a, mpd_context_t *ctx);
+void mpd_sset_u32(mpd_t *result, uint32_t a, mpd_context_t *ctx);
+void mpd_set_ssize(mpd_t *result, mpd_ssize_t a, mpd_context_t *ctx);
+void mpd_set_i32(mpd_t *result, int32_t a, mpd_context_t *ctx);
+void mpd_set_uint(mpd_t *result, mpd_uint_t a, mpd_context_t *ctx);
+void mpd_set_u32(mpd_t *result, uint32_t a, mpd_context_t *ctx);
+#ifndef LEGACY_COMPILER
+void mpd_set_i64(mpd_t *result, int64_t a, mpd_context_t *ctx);
+void mpd_set_u64(mpd_t *result, uint64_t a, mpd_context_t *ctx);
+#endif
+mpd_ssize_t mpd_get_ssize(const mpd_t *a, mpd_context_t *ctx);
+mpd_uint_t mpd_get_uint(const mpd_t *a, mpd_context_t *ctx);
+mpd_uint_t mpd_abs_uint(const mpd_t *a, mpd_context_t *ctx);
+void mpd_and(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_copy(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_canonical(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_copy_abs(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_copy_negate(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_copy_sign(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_invert(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_logb(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_or(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_rotate(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_scaleb(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_shiftl(mpd_t *result, const mpd_t *a, mpd_ssize_t n, mpd_context_t *ctx);
+mpd_uint_t mpd_shiftr(mpd_t *result, const mpd_t *a, mpd_ssize_t n, mpd_context_t *ctx);
+void mpd_shiftn(mpd_t *result, const mpd_t *a, mpd_ssize_t n, mpd_context_t *ctx);
+void mpd_shift(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_xor(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_abs(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+int mpd_cmp(const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+int mpd_compare(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+int mpd_compare_signal(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_add(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_add_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, mpd_context_t *ctx);
+void mpd_add_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx);
+void mpd_add_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, mpd_context_t *ctx);
+void mpd_add_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx);
+void mpd_sub(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_sub_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, mpd_context_t *ctx);
+void mpd_sub_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx);
+void mpd_sub_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, mpd_context_t *ctx);
+void mpd_sub_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx);
+void mpd_div(mpd_t *q, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_div_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, mpd_context_t *ctx);
+void mpd_div_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx);
+void mpd_div_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, mpd_context_t *ctx);
+void mpd_div_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx);
+void mpd_divmod(mpd_t *q, mpd_t *r, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_divint(mpd_t *q, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_exp(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_fma(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_t *c, mpd_context_t *ctx);
+void mpd_ln(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_log10(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_max(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_max_mag(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_min(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_min_mag(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_minus(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_mul(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_mul_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, mpd_context_t *ctx);
+void mpd_mul_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx);
+void mpd_mul_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, mpd_context_t *ctx);
+void mpd_mul_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx);
+void mpd_next_minus(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_next_plus(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_next_toward(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_plus(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_pow(mpd_t *result, const mpd_t *base, const mpd_t *exp, mpd_context_t *ctx);
+void mpd_powmod(mpd_t *result, const mpd_t *base, const mpd_t *exp, const mpd_t *mod, mpd_context_t *ctx);
+void mpd_quantize(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_rescale(mpd_t *result, const mpd_t *a, mpd_ssize_t exp, mpd_context_t *ctx);
+void mpd_reduce(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_rem(mpd_t *r, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_rem_near(mpd_t *r, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_round_to_intx(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_round_to_int(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_trunc(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_floor(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_ceil(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_sqrt(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_invroot(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+
+
+/******************************************************************************/
+/*                          Configuration specific                            */
+/******************************************************************************/
+
+#ifdef CONFIG_64
+void mpd_qsset_i64(mpd_t *result, int64_t a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qsset_u64(mpd_t *result, uint64_t a, const mpd_context_t *ctx, uint32_t *status);
+int64_t mpd_qget_i64(const mpd_t *dec, uint32_t *status);
+uint64_t mpd_qget_u64(const mpd_t *dec, uint32_t *status);
+
+void mpd_qadd_i64(mpd_t *result, const mpd_t *a, int64_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qadd_u64(mpd_t *result, const mpd_t *a, uint64_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qsub_i64(mpd_t *result, const mpd_t *a, int64_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qsub_u64(mpd_t *result, const mpd_t *a, uint64_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qmul_i64(mpd_t *result, const mpd_t *a, int64_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qmul_u64(mpd_t *result, const mpd_t *a, uint64_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qdiv_i64(mpd_t *result, const mpd_t *a, int64_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qdiv_u64(mpd_t *result, const mpd_t *a, uint64_t b, const mpd_context_t *ctx, uint32_t *status);
+
+void mpd_sset_i64(mpd_t *result, int64_t a, mpd_context_t *ctx);
+void mpd_sset_u64(mpd_t *result, uint64_t a, mpd_context_t *ctx);
+int64_t mpd_get_i64(const mpd_t *a, mpd_context_t *ctx);
+uint64_t mpd_get_u64(const mpd_t *a, mpd_context_t *ctx);
+
+void mpd_add_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx);
+void mpd_add_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx);
+void mpd_sub_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx);
+void mpd_sub_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx);
+void mpd_div_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx);
+void mpd_div_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx);
+void mpd_mul_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx);
+void mpd_mul_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx);
+#else
+int32_t mpd_qget_i32(const mpd_t *dec, uint32_t *status);
+uint32_t mpd_qget_u32(const mpd_t *dec, uint32_t *status);
+int32_t mpd_get_i32(const mpd_t *a, mpd_context_t *ctx);
+uint32_t mpd_get_u32(const mpd_t *a, mpd_context_t *ctx);
+#endif
+
+
+/******************************************************************************/
+/*                       Get attributes of a decimal                          */
+/******************************************************************************/
+
+mpd_ssize_t mpd_adjexp(const mpd_t *dec);
+mpd_ssize_t mpd_etiny(const mpd_context_t *ctx);
+mpd_ssize_t mpd_etop(const mpd_context_t *ctx);
+mpd_uint_t mpd_msword(const mpd_t *dec);
+int mpd_word_digits(mpd_uint_t word);
+/* most significant digit of a word */
+mpd_uint_t mpd_msd(mpd_uint_t word);
+/* least significant digit of a word */
+mpd_uint_t mpd_lsd(mpd_uint_t word);
+/* coefficient size needed to store 'digits' */
+mpd_ssize_t mpd_digits_to_size(mpd_ssize_t digits);
+/* number of digits in the exponent, undefined for MPD_SSIZE_MIN */
+int mpd_exp_digits(mpd_ssize_t exp);
+int mpd_iscanonical(const mpd_t *dec UNUSED);
+int mpd_isfinite(const mpd_t *dec);
+int mpd_isinfinite(const mpd_t *dec);
+int mpd_isinteger(const mpd_t *dec);
+int mpd_isnan(const mpd_t *dec);
+int mpd_isnegative(const mpd_t *dec);
+int mpd_ispositive(const mpd_t *dec);
+int mpd_isqnan(const mpd_t *dec);
+int mpd_issigned(const mpd_t *dec);
+int mpd_issnan(const mpd_t *dec);
+int mpd_isspecial(const mpd_t *dec);
+int mpd_iszero(const mpd_t *dec);
+/* undefined for special numbers */
+int mpd_iszerocoeff(const mpd_t *dec);
+int mpd_isnormal(const mpd_t *dec, const mpd_context_t *ctx);
+int mpd_issubnormal(const mpd_t *dec, const mpd_context_t *ctx);
+/* odd word */
+int mpd_isoddword(mpd_uint_t word);
+/* odd coefficient */
+int mpd_isoddcoeff(const mpd_t *dec);
+/* odd decimal, only defined for integers */
+int mpd_isodd(const mpd_t *dec);
+/* even decimal, only defined for integers */
+int mpd_iseven(const mpd_t *dec);
+/* 0 if dec is positive, 1 if dec is negative */
+uint8_t mpd_sign(const mpd_t *dec);
+/* 1 if dec is positive, -1 if dec is negative */
+int mpd_arith_sign(const mpd_t *dec);
+long mpd_radix(void);
+int mpd_isdynamic(mpd_t *dec);
+int mpd_isstatic(mpd_t *dec);
+int mpd_isdynamic_data(mpd_t *dec);
+int mpd_isstatic_data(mpd_t *dec);
+int mpd_isshared_data(mpd_t *dec);
+int mpd_isconst_data(mpd_t *dec);
+mpd_ssize_t mpd_trail_zeros(const mpd_t *dec);
+
+
+/******************************************************************************/
+/*                       Set attributes of a decimal                          */
+/******************************************************************************/
+
+/* set number of decimal digits in the coefficient */
+void mpd_setdigits(mpd_t *result);
+void mpd_set_sign(mpd_t *result, uint8_t sign);
+/* copy sign from another decimal */
+void mpd_signcpy(mpd_t *result, mpd_t *a);
+void mpd_set_infinity(mpd_t *result);
+void mpd_set_qnan(mpd_t *result);
+void mpd_set_snan(mpd_t *result);
+void mpd_set_negative(mpd_t *result);
+void mpd_set_positive(mpd_t *result);
+void mpd_set_dynamic(mpd_t *result);
+void mpd_set_static(mpd_t *result);
+void mpd_set_dynamic_data(mpd_t *result);
+void mpd_set_static_data(mpd_t *result);
+void mpd_set_shared_data(mpd_t *result);
+void mpd_set_const_data(mpd_t *result);
+void mpd_clear_flags(mpd_t *result);
+void mpd_set_flags(mpd_t *result, uint8_t flags);
+void mpd_copy_flags(mpd_t *result, const mpd_t *a);
+
+
+/******************************************************************************/
+/*                              Error Macros                                  */
+/******************************************************************************/
+
+#define mpd_err_fatal(...) \
+        do {fprintf(stderr, "%s:%d: error: ", __FILE__, __LINE__); \
+            fprintf(stderr, __VA_ARGS__);  fputc('\n', stderr); \
+            exit(1); \
+        } while (0)
+#define mpd_err_warn(...) \
+        do {fprintf(stderr, "%s:%d: warning: ", __FILE__, __LINE__); \
+            fprintf(stderr, __VA_ARGS__); fputc('\n', stderr); \
+        } while (0)
+
+
+/******************************************************************************/
+/*                            Memory handling                                 */
+/******************************************************************************/
+
+extern void *(* mpd_mallocfunc)(size_t size);
+extern void *(* mpd_callocfunc)(size_t nmemb, size_t size);
+extern void *(* mpd_reallocfunc)(void *ptr, size_t size);
+extern void (* mpd_free)(void *ptr);
+
+void *mpd_callocfunc_em(size_t nmemb, size_t size);
+
+void *mpd_alloc(mpd_size_t nmemb, mpd_size_t size);
+void *mpd_calloc(mpd_size_t nmemb, mpd_size_t size);
+void *mpd_realloc(void *ptr, mpd_size_t nmemb, mpd_size_t size, uint8_t *err);
+void *mpd_sh_alloc(mpd_size_t struct_size, mpd_size_t nmemb, mpd_size_t size);
+
+mpd_t *mpd_qnew(void);
+mpd_t *mpd_new(mpd_context_t *ctx);
+mpd_t *mpd_qnew_size(mpd_ssize_t size);
+void mpd_del(mpd_t *dec);
+
+void mpd_uint_zero(mpd_uint_t *dest, mpd_size_t len);
+int mpd_qresize(mpd_t *result, mpd_ssize_t size, uint32_t *status);
+int mpd_qresize_zero(mpd_t *result, mpd_ssize_t size, uint32_t *status);
+void mpd_minalloc(mpd_t *result);
+
+int mpd_resize(mpd_t *result, mpd_ssize_t size, mpd_context_t *ctx);
+int mpd_resize_zero(mpd_t *result, mpd_ssize_t size, mpd_context_t *ctx);
+
+
+#ifdef __cplusplus
+} /* END extern "C" */
+#endif
+
+
+#endif /* MPDECIMAL_32_H */
+
+
+

+ 751 - 0
mpdecimal/mpdecimal.64.h

@@ -0,0 +1,751 @@
+/*
+ * Copyright (c) 2008-2010 Stefan Krah. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#ifndef MPDECIMAL_64_H
+#define MPDECIMAL_64_H
+
+
+#ifdef __cplusplus
+extern "C" {
+#define __STDC_LIMIT_MACROS
+#endif
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <assert.h>
+#include <stdint.h>
+
+
+#if !defined(__GNUC_STDC_INLINE__)
+  #define __GNUC_STDC_INLINE__
+#endif
+#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
+  #define UNUSED __attribute__((unused))
+#else
+  #define UNUSED
+#endif
+
+
+/******************************************************************************/
+/*                              Configuration                                 */
+/******************************************************************************/
+
+/* ABI: 64-bit */
+#ifdef CONFIG_32
+  #error "cannot use CONFIG_32 with 64-bit header."
+#endif
+
+#ifndef CONFIG_64
+  #define CONFIG_64
+#endif
+
+
+/* BEGIN CONFIG_64 */
+#if defined(CONFIG_64)
+/* types for modular and base arithmetic */
+#define MPD_UINT_MAX UINT64_MAX
+#define MPD_BITS_PER_UINT 64
+typedef uint64_t mpd_uint_t;  /* unsigned mod type */
+
+#define MPD_SIZE_MAX SIZE_MAX
+typedef size_t mpd_size_t; /* unsigned size type */
+
+/* type for exp, digits, len, prec */
+#define MPD_SSIZE_MAX INT64_MAX
+#define MPD_SSIZE_MIN INT64_MIN
+typedef int64_t mpd_ssize_t;
+#define _mpd_strtossize strtoll
+
+/* decimal arithmetic */
+#define MPD_RADIX 10000000000000000000ULL  /* 10**19 */
+#define MPD_RDIGITS 19
+#define MPD_MAX_POW10 19
+#define MPD_EXPDIGITS 19  /* MPD_EXPDIGITS <= MPD_RDIGITS+1 */
+
+#define MPD_MAXTRANSFORM_2N 4294967296ULL      /* 2**32 */
+#define MPD_MAX_PREC 999999999999999999LL
+#define MPD_MAX_PREC_LOG2 64
+#define MPD_ELIMIT  1000000000000000000LL
+#define MPD_MAX_EMAX   999999999999999999LL    /* ELIMIT-1 */
+#define MPD_MIN_EMIN  (-999999999999999999LL)  /* -EMAX */
+#define MPD_MIN_ETINY (MPD_MIN_EMIN-(MPD_MAX_PREC-1))
+#define MPD_EXP_INF 2000000000000000001LL
+#define MPD_EXP_CLAMP (-4000000000000000001LL)
+#define MPD_MAXIMPORT 105263157894736842L /* ceil((2*MPD_MAX_PREC)/MPD_RDIGITS) */
+/* END CONFIG_64 */
+
+
+/* BEGIN CONFIG_32 */
+#elif defined(CONFIG_32)
+/* types for modular and base arithmetic */
+#define MPD_UINT_MAX UINT32_MAX
+#define MPD_BITS_PER_UINT 32
+typedef uint32_t mpd_uint_t;  /* unsigned mod type */
+
+#ifndef LEGACY_COMPILER
+#define MPD_UUINT_MAX UINT64_MAX
+typedef uint64_t mpd_uuint_t; /* double width unsigned mod type */
+#endif
+
+#define MPD_SIZE_MAX SIZE_MAX
+typedef size_t mpd_size_t; /* unsigned size type */
+
+/* type for dec->len, dec->exp, ctx->prec */
+#define MPD_SSIZE_MAX INT32_MAX
+#define MPD_SSIZE_MIN INT32_MIN
+typedef int32_t mpd_ssize_t;
+#define _mpd_strtossize strtol
+
+/* decimal arithmetic */
+#define MPD_RADIX 1000000000UL  /* 10**9 */
+#define MPD_RDIGITS 9
+#define MPD_MAX_POW10 9
+#define MPD_EXPDIGITS 10 /* MPD_EXPDIGITS <= MPD_RDIGITS+1 */
+
+#define MPD_MAXTRANSFORM_2N 33554432UL /* 2**25 */
+#define MPD_MAX_PREC 425000000L
+#define MPD_MAX_PREC_LOG2 32
+#define MPD_ELIMIT 425000001L
+#define MPD_MAX_EMAX 425000000L        /* ELIMIT-1 */
+#define MPD_MIN_EMIN (-425000000L)     /* -EMAX */
+#define MPD_MIN_ETINY (MPD_MIN_EMIN-(MPD_MAX_PREC-1))
+#define MPD_EXP_INF 1000000001L      /* allows for emax=999999999 in the tests */
+#define MPD_EXP_CLAMP (-2000000001L) /* allows for emin=-999999999 in the tests */
+#define MPD_MAXIMPORT 94444445L      /* ceil((2*MPD_MAX_PREC)/MPD_RDIGITS) */
+/* END CONFIG_32 */
+
+#else
+  #error "define CONFIG_64 or CONFIG_32"
+#endif
+/* END CONFIG */
+
+
+#if MPD_SIZE_MAX != MPD_UINT_MAX
+  #error "unsupported platform: need mpd_size_t == mpd_uint_t"
+#endif
+
+
+/******************************************************************************/
+/*                                Context                                     */
+/******************************************************************************/
+
+enum {
+	MPD_ROUND_UP,          /* round away from 0               */
+	MPD_ROUND_DOWN,        /* round toward 0 (truncate)       */
+	MPD_ROUND_CEILING,     /* round toward +infinity          */
+	MPD_ROUND_FLOOR,       /* round toward -infinity          */
+	MPD_ROUND_HALF_UP,     /* 0.5 is rounded up               */
+	MPD_ROUND_HALF_DOWN,   /* 0.5 is rounded down             */
+	MPD_ROUND_HALF_EVEN,   /* 0.5 is rounded to even          */
+	MPD_ROUND_05UP,        /* round zero or five away from 0  */
+	MPD_ROUND_TRUNC,       /* truncate, but set infinity      */
+	MPD_ROUND_GUARD
+};
+
+enum { MPD_CLAMP_DEFAULT, MPD_CLAMP_IEEE_754, MPD_CLAMP_GUARD };
+
+extern const char *mpd_round_string[MPD_ROUND_GUARD];
+extern const char *mpd_clamp_string[MPD_CLAMP_GUARD];
+
+
+typedef struct {
+	mpd_ssize_t prec;   /* precision */
+	mpd_ssize_t emax;   /* max positive exp */
+	mpd_ssize_t emin;   /* min negative exp */
+	uint32_t traps;     /* status events that should be trapped */
+	uint32_t status;    /* status flags */
+	uint32_t newtrap;   /* set by mpd_addstatus_raise() */
+	int      round;     /* rounding mode */
+	int      clamp;     /* clamp mode */
+	int      allcr;     /* all functions correctly rounded */
+} mpd_context_t;
+
+
+/* Status flags */
+#define MPD_Clamped             0x00000001U
+#define MPD_Conversion_syntax   0x00000002U
+#define MPD_Division_by_zero    0x00000004U
+#define MPD_Division_impossible 0x00000008U
+#define MPD_Division_undefined  0x00000010U
+#define MPD_Fpu_error           0x00000020U
+#define MPD_Inexact             0x00000040U
+#define MPD_Invalid_context     0x00000080U
+#define MPD_Invalid_operation   0x00000100U
+#define MPD_Malloc_error        0x00000200U
+#define MPD_Not_implemented     0x00000400U
+#define MPD_Overflow            0x00000800U
+#define MPD_Rounded             0x00001000U
+#define MPD_Subnormal           0x00002000U
+#define MPD_Underflow           0x00004000U
+#define MPD_Max_status         (0x00008000U-1U)
+
+/* Conditions that result in an IEEE 754 exception */
+#define MPD_IEEE_Invalid_operation (MPD_Conversion_syntax |   \
+                                    MPD_Division_impossible | \
+                                    MPD_Division_undefined |  \
+                                    MPD_Fpu_error |           \
+                                    MPD_Invalid_context |     \
+                                    MPD_Invalid_operation |   \
+                                    MPD_Malloc_error)         \
+
+/* Errors that require the result of an operation to be set to NaN */
+#define MPD_Errors (MPD_IEEE_Invalid_operation | \
+                    MPD_Division_by_zero)
+
+/* Default traps */
+#define MPD_Traps (MPD_IEEE_Invalid_operation | \
+                   MPD_Division_by_zero |       \
+                   MPD_Overflow |               \
+                   MPD_Underflow)
+
+/* Official name */
+#define MPD_Insufficient_storage MPD_Malloc_error
+
+/* IEEE 754 interchange format contexts */
+#define MPD_IEEE_CONTEXT_MAX_BITS 512 /* 16*(log2(MPD_MAX_EMAX / 3)-3) */
+#define MPD_DECIMAL32 32
+#define MPD_DECIMAL64 64
+#define MPD_DECIMAL128 128
+
+
+#define MPD_MINALLOC_MIN 2
+#define MPD_MINALLOC_MAX 64
+extern mpd_ssize_t MPD_MINALLOC;
+extern void (* mpd_traphandler)(mpd_context_t *);
+void mpd_dflt_traphandler(mpd_context_t *);
+
+void mpd_setminalloc(mpd_ssize_t n);
+void mpd_init(mpd_context_t *ctx, mpd_ssize_t prec);
+
+void mpd_maxcontext(mpd_context_t *ctx);
+void mpd_maxcontext_plus(mpd_context_t *workctx, const mpd_context_t *ctx);
+void mpd_defaultcontext(mpd_context_t *ctx);
+void mpd_basiccontext(mpd_context_t *ctx);
+int mpd_ieee_context(mpd_context_t *ctx, int bits);
+
+mpd_ssize_t mpd_getprec(const mpd_context_t *ctx);
+mpd_ssize_t mpd_getemax(const mpd_context_t *ctx);
+mpd_ssize_t mpd_getemin(const mpd_context_t *ctx);
+int mpd_getround(const mpd_context_t *ctx);
+uint32_t mpd_gettraps(const mpd_context_t *ctx);
+uint32_t mpd_getstatus(const mpd_context_t *ctx);
+int mpd_getclamp(const mpd_context_t *ctx);
+int mpd_getcr(const mpd_context_t *ctx);
+
+int mpd_qsetprec(mpd_context_t *ctx, mpd_ssize_t prec);
+int mpd_qsetemax(mpd_context_t *ctx, mpd_ssize_t emax);
+int mpd_qsetemin(mpd_context_t *ctx, mpd_ssize_t emin);
+int mpd_qsetround(mpd_context_t *ctx, int newround);
+int mpd_qsettraps(mpd_context_t *ctx, uint32_t flags);
+int mpd_qsetstatus(mpd_context_t *ctx, uint32_t flags);
+int mpd_qsetclamp(mpd_context_t *ctx, int c);
+int mpd_qsetcr(mpd_context_t *ctx, int c);
+void mpd_addstatus_raise(mpd_context_t *ctx, uint32_t flags);
+
+
+/******************************************************************************/
+/*                           Decimal Arithmetic                               */
+/******************************************************************************/
+
+/* mpd_t flags */
+#define MPD_POS                 ((uint8_t)0)
+#define MPD_NEG                 ((uint8_t)1)
+#define MPD_INF                 ((uint8_t)2)
+#define MPD_NAN                 ((uint8_t)4)
+#define MPD_SNAN                ((uint8_t)8)
+#define MPD_SPECIAL (MPD_INF|MPD_NAN|MPD_SNAN)
+#define MPD_STATIC              ((uint8_t)16)
+#define MPD_STATIC_DATA         ((uint8_t)32)
+#define MPD_SHARED_DATA         ((uint8_t)64)
+#define MPD_CONST_DATA          ((uint8_t)128)
+#define MPD_DATAFLAGS (MPD_STATIC_DATA|MPD_SHARED_DATA|MPD_CONST_DATA)
+
+/* mpd_t */
+typedef struct {
+	uint8_t flags;
+	mpd_ssize_t exp;
+	mpd_ssize_t digits;
+	mpd_ssize_t len;
+	mpd_ssize_t alloc;
+	mpd_uint_t *data;
+} mpd_t;
+
+
+typedef unsigned char uchar;
+extern mpd_t mpd_ln10;
+
+
+/******************************************************************************/
+/*                       Quiet, thread-safe functions                         */
+/******************************************************************************/
+
+/* format specification */
+typedef struct {
+	mpd_ssize_t min_width; /* minimum field width */
+	mpd_ssize_t prec;      /* fraction digits or significant digits */
+	char type;             /* conversion specifier */
+	char align;            /* alignment */
+	char sign;             /* sign printing/alignment */
+	char fill[5];          /* fill character */
+	const char *dot;       /* decimal point */
+	const char *sep;       /* thousands separator */
+	const char *grouping;  /* grouping of digits */
+} mpd_spec_t;
+
+/* output to a string */
+char *mpd_to_sci(const mpd_t *dec, int fmt);
+char *mpd_to_eng(const mpd_t *dec, int fmt);
+int mpd_parse_fmt_str(mpd_spec_t *spec, const char *fmt, int caps);
+char * mpd_qformat_spec(const mpd_t *dec, mpd_spec_t *spec, const mpd_context_t *ctx, uint32_t *status);
+char *mpd_qformat(const mpd_t *dec, const char *fmt, const mpd_context_t *ctx, uint32_t *status);
+
+#define MPD_NUM_FLAGS 15
+#define MPD_MAX_FLAG_STRING 208
+#define MPD_MAX_FLAG_LIST (MPD_MAX_FLAG_STRING+18)
+#define MPD_MAX_SIGNAL_LIST 121
+int mpd_snprint_flags(char *dest, int nmemb, uint32_t flags);
+int mpd_lsnprint_flags(char *dest, int nmemb, uint32_t flags, const char *flag_string[]);
+int mpd_lsnprint_signals(char *dest, int nmemb, uint32_t flags, const char *signal_string[]);
+
+/* output to a file */
+void mpd_fprint(FILE *file, const mpd_t *dec);
+void mpd_print(const mpd_t *dec);
+
+/* assignment from a string */
+void mpd_qset_string(mpd_t *dec, const char *s, const mpd_context_t *ctx, uint32_t *status);
+
+/* set to NaN with error flags */
+void mpd_seterror(mpd_t *result, uint32_t flags, uint32_t *status);
+/* set a special with sign and type */
+void mpd_setspecial(mpd_t *dec, uint8_t sign, uint8_t type);
+/* set coefficient to zero or all nines */
+void mpd_zerocoeff(mpd_t *result);
+void mpd_qmaxcoeff(mpd_t *result, const mpd_context_t *ctx, uint32_t *status);
+
+/* quietly assign a C integer type to an mpd_t */
+void mpd_qset_ssize(mpd_t *result, mpd_ssize_t a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qset_i32(mpd_t *result, int32_t a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qset_uint(mpd_t *result, mpd_uint_t a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qset_u32(mpd_t *result, uint32_t a, const mpd_context_t *ctx, uint32_t *status);
+#ifndef LEGACY_COMPILER
+void mpd_qset_i64(mpd_t *result, int64_t a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qset_u64(mpd_t *result, uint64_t a, const mpd_context_t *ctx, uint32_t *status);
+#endif
+
+/* quietly assign a C integer type to an mpd_t with a static coefficient */
+void mpd_qsset_ssize(mpd_t *result, mpd_ssize_t a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qsset_i32(mpd_t *result, int32_t a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qsset_uint(mpd_t *result, mpd_uint_t a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qsset_u32(mpd_t *result, uint32_t a, const mpd_context_t *ctx, uint32_t *status);
+
+/* quietly get a C integer type from an mpd_t */
+mpd_ssize_t mpd_qget_ssize(const mpd_t *dec, uint32_t *status);
+mpd_uint_t mpd_qget_uint(const mpd_t *dec, uint32_t *status);
+mpd_uint_t mpd_qabs_uint(const mpd_t *dec, uint32_t *status);
+
+
+/* quiet functions */
+int mpd_qcheck_nan(mpd_t *nanresult, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+int mpd_qcheck_nans(mpd_t *nanresult, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qfinalize(mpd_t *result, const mpd_context_t *ctx, uint32_t *status);
+
+const char * mpd_class(const mpd_t *a, const mpd_context_t *ctx);
+
+int mpd_qcopy(mpd_t *result, const mpd_t *a,  uint32_t *status);
+mpd_t *mpd_qncopy(const mpd_t *a);
+int mpd_qcopy_abs(mpd_t *result, const mpd_t *a, uint32_t *status);
+int mpd_qcopy_negate(mpd_t *result, const mpd_t *a, uint32_t *status);
+int mpd_qcopy_sign(mpd_t *result, const mpd_t *a, const mpd_t *b, uint32_t *status);
+
+void mpd_qand(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qinvert(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qlogb(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qor(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qscaleb(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qxor(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+int mpd_same_quantum(const mpd_t *a, const mpd_t *b);
+
+void mpd_qrotate(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+int mpd_qshiftl(mpd_t *result, const mpd_t *a, mpd_ssize_t n, uint32_t *status);
+mpd_uint_t mpd_qshiftr(mpd_t *result, const mpd_t *a, mpd_ssize_t n, uint32_t *status);
+mpd_uint_t mpd_qshiftr_inplace(mpd_t *result, mpd_ssize_t n);
+void mpd_qshift(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qshiftn(mpd_t *result, const mpd_t *a, mpd_ssize_t n, const mpd_context_t *ctx, uint32_t *status);
+
+int mpd_qcmp(const mpd_t *a, const mpd_t *b, uint32_t *status);
+int mpd_qcompare(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+int mpd_qcompare_signal(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+int mpd_cmp_total(const mpd_t *a, const mpd_t *b);
+int mpd_cmp_total_mag(const mpd_t *a, const mpd_t *b);
+int mpd_compare_total(mpd_t *result, const mpd_t *a, const mpd_t *b);
+int mpd_compare_total_mag(mpd_t *result, const mpd_t *a, const mpd_t *b);
+
+void mpd_qround_to_intx(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qround_to_int(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qtrunc(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qfloor(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qceil(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+
+void mpd_qabs(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qmax(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qmax_mag(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qmin(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qmin_mag(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qminus(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qplus(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qnext_minus(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qnext_plus(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qnext_toward(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qquantize(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qrescale(mpd_t *result, const mpd_t *a, mpd_ssize_t exp, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qreduce(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qadd(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qadd_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qadd_i32(mpd_t *result, const mpd_t *a, int32_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qadd_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qadd_u32(mpd_t *result, const mpd_t *a, uint32_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qsub(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qsub_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qsub_i32(mpd_t *result, const mpd_t *a, int32_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qsub_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qsub_u32(mpd_t *result, const mpd_t *a, uint32_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qmul(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qmul_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qmul_i32(mpd_t *result, const mpd_t *a, int32_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qmul_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qmul_u32(mpd_t *result, const mpd_t *a, uint32_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qfma(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_t *c, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qdiv(mpd_t *q, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qdiv_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qdiv_i32(mpd_t *result, const mpd_t *a, int32_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qdiv_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qdiv_u32(mpd_t *result, const mpd_t *a, uint32_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qdivint(mpd_t *q, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qrem(mpd_t *r, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qrem_near(mpd_t *r, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qdivmod(mpd_t *q, mpd_t *r, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qpow(mpd_t *result, const mpd_t *base, const mpd_t *exp, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qpowmod(mpd_t *result, const mpd_t *base, const mpd_t *exp, const mpd_t *mod, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qexp(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_update_ln10(mpd_ssize_t prec, uint32_t *status);
+void mpd_qln(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qlog10(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qsqrt(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qinvroot(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+
+
+size_t mpd_sizeinbase(mpd_t *a, uint32_t base);
+void mpd_qimport_u16(mpd_t *result, const uint16_t *srcdata, size_t srclen,
+                     uint8_t srcsign, uint32_t srcbase,
+                     const mpd_context_t *ctx, uint32_t *status);
+void mpd_qimport_u32(mpd_t *result, const uint32_t *srcdata, size_t srclen,
+                     uint8_t srcsign, uint32_t srcbase,
+                     const mpd_context_t *ctx, uint32_t *status);
+size_t mpd_qexport_u16(uint16_t *rdata, size_t rlen, uint32_t base,
+                       const mpd_t *src, uint32_t *status);
+size_t mpd_qexport_u32(uint32_t *rdata, size_t rlen, uint32_t base,
+                       const mpd_t *src, uint32_t *status);
+
+
+/******************************************************************************/
+/*                           Signalling functions                             */
+/******************************************************************************/
+
+char * mpd_format(const mpd_t *dec, const char *fmt, mpd_context_t *ctx);
+void mpd_import_u16(mpd_t *result, const uint16_t *srcdata, size_t srclen, uint8_t srcsign, uint32_t base, mpd_context_t *ctx);
+void mpd_import_u32(mpd_t *result, const uint32_t *srcdata, size_t srclen, uint8_t srcsign, uint32_t base, mpd_context_t *ctx);
+size_t mpd_export_u16(uint16_t *rdata, size_t rlen, uint32_t base, const mpd_t *src, mpd_context_t *ctx);
+size_t mpd_export_u32(uint32_t *rdata, size_t rlen, uint32_t base, const mpd_t *src, mpd_context_t *ctx);
+void mpd_finalize(mpd_t *result, mpd_context_t *ctx);
+int mpd_check_nan(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+int mpd_check_nans(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_set_string(mpd_t *result, const char *s, mpd_context_t *ctx);
+void mpd_maxcoeff(mpd_t *result, mpd_context_t *ctx);
+void mpd_sset_ssize(mpd_t *result, mpd_ssize_t a, mpd_context_t *ctx);
+void mpd_sset_i32(mpd_t *result, int32_t a, mpd_context_t *ctx);
+void mpd_sset_uint(mpd_t *result, mpd_uint_t a, mpd_context_t *ctx);
+void mpd_sset_u32(mpd_t *result, uint32_t a, mpd_context_t *ctx);
+void mpd_set_ssize(mpd_t *result, mpd_ssize_t a, mpd_context_t *ctx);
+void mpd_set_i32(mpd_t *result, int32_t a, mpd_context_t *ctx);
+void mpd_set_uint(mpd_t *result, mpd_uint_t a, mpd_context_t *ctx);
+void mpd_set_u32(mpd_t *result, uint32_t a, mpd_context_t *ctx);
+#ifndef LEGACY_COMPILER
+void mpd_set_i64(mpd_t *result, int64_t a, mpd_context_t *ctx);
+void mpd_set_u64(mpd_t *result, uint64_t a, mpd_context_t *ctx);
+#endif
+mpd_ssize_t mpd_get_ssize(const mpd_t *a, mpd_context_t *ctx);
+mpd_uint_t mpd_get_uint(const mpd_t *a, mpd_context_t *ctx);
+mpd_uint_t mpd_abs_uint(const mpd_t *a, mpd_context_t *ctx);
+void mpd_and(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_copy(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_canonical(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_copy_abs(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_copy_negate(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_copy_sign(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_invert(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_logb(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_or(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_rotate(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_scaleb(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_shiftl(mpd_t *result, const mpd_t *a, mpd_ssize_t n, mpd_context_t *ctx);
+mpd_uint_t mpd_shiftr(mpd_t *result, const mpd_t *a, mpd_ssize_t n, mpd_context_t *ctx);
+void mpd_shiftn(mpd_t *result, const mpd_t *a, mpd_ssize_t n, mpd_context_t *ctx);
+void mpd_shift(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_xor(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_abs(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+int mpd_cmp(const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+int mpd_compare(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+int mpd_compare_signal(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_add(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_add_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, mpd_context_t *ctx);
+void mpd_add_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx);
+void mpd_add_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, mpd_context_t *ctx);
+void mpd_add_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx);
+void mpd_sub(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_sub_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, mpd_context_t *ctx);
+void mpd_sub_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx);
+void mpd_sub_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, mpd_context_t *ctx);
+void mpd_sub_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx);
+void mpd_div(mpd_t *q, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_div_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, mpd_context_t *ctx);
+void mpd_div_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx);
+void mpd_div_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, mpd_context_t *ctx);
+void mpd_div_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx);
+void mpd_divmod(mpd_t *q, mpd_t *r, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_divint(mpd_t *q, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_exp(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_fma(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_t *c, mpd_context_t *ctx);
+void mpd_ln(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_log10(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_max(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_max_mag(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_min(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_min_mag(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_minus(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_mul(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_mul_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, mpd_context_t *ctx);
+void mpd_mul_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx);
+void mpd_mul_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, mpd_context_t *ctx);
+void mpd_mul_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx);
+void mpd_next_minus(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_next_plus(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_next_toward(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_plus(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_pow(mpd_t *result, const mpd_t *base, const mpd_t *exp, mpd_context_t *ctx);
+void mpd_powmod(mpd_t *result, const mpd_t *base, const mpd_t *exp, const mpd_t *mod, mpd_context_t *ctx);
+void mpd_quantize(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_rescale(mpd_t *result, const mpd_t *a, mpd_ssize_t exp, mpd_context_t *ctx);
+void mpd_reduce(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_rem(mpd_t *r, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_rem_near(mpd_t *r, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_round_to_intx(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_round_to_int(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_trunc(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_floor(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_ceil(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_sqrt(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_invroot(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+
+
+/******************************************************************************/
+/*                          Configuration specific                            */
+/******************************************************************************/
+
+#ifdef CONFIG_64
+void mpd_qsset_i64(mpd_t *result, int64_t a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qsset_u64(mpd_t *result, uint64_t a, const mpd_context_t *ctx, uint32_t *status);
+int64_t mpd_qget_i64(const mpd_t *dec, uint32_t *status);
+uint64_t mpd_qget_u64(const mpd_t *dec, uint32_t *status);
+
+void mpd_qadd_i64(mpd_t *result, const mpd_t *a, int64_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qadd_u64(mpd_t *result, const mpd_t *a, uint64_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qsub_i64(mpd_t *result, const mpd_t *a, int64_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qsub_u64(mpd_t *result, const mpd_t *a, uint64_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qmul_i64(mpd_t *result, const mpd_t *a, int64_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qmul_u64(mpd_t *result, const mpd_t *a, uint64_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qdiv_i64(mpd_t *result, const mpd_t *a, int64_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qdiv_u64(mpd_t *result, const mpd_t *a, uint64_t b, const mpd_context_t *ctx, uint32_t *status);
+
+void mpd_sset_i64(mpd_t *result, int64_t a, mpd_context_t *ctx);
+void mpd_sset_u64(mpd_t *result, uint64_t a, mpd_context_t *ctx);
+int64_t mpd_get_i64(const mpd_t *a, mpd_context_t *ctx);
+uint64_t mpd_get_u64(const mpd_t *a, mpd_context_t *ctx);
+
+void mpd_add_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx);
+void mpd_add_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx);
+void mpd_sub_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx);
+void mpd_sub_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx);
+void mpd_div_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx);
+void mpd_div_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx);
+void mpd_mul_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx);
+void mpd_mul_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx);
+#else
+int32_t mpd_qget_i32(const mpd_t *dec, uint32_t *status);
+uint32_t mpd_qget_u32(const mpd_t *dec, uint32_t *status);
+int32_t mpd_get_i32(const mpd_t *a, mpd_context_t *ctx);
+uint32_t mpd_get_u32(const mpd_t *a, mpd_context_t *ctx);
+#endif
+
+
+/******************************************************************************/
+/*                       Get attributes of a decimal                          */
+/******************************************************************************/
+
+mpd_ssize_t mpd_adjexp(const mpd_t *dec);
+mpd_ssize_t mpd_etiny(const mpd_context_t *ctx);
+mpd_ssize_t mpd_etop(const mpd_context_t *ctx);
+mpd_uint_t mpd_msword(const mpd_t *dec);
+int mpd_word_digits(mpd_uint_t word);
+/* most significant digit of a word */
+mpd_uint_t mpd_msd(mpd_uint_t word);
+/* least significant digit of a word */
+mpd_uint_t mpd_lsd(mpd_uint_t word);
+/* coefficient size needed to store 'digits' */
+mpd_ssize_t mpd_digits_to_size(mpd_ssize_t digits);
+/* number of digits in the exponent, undefined for MPD_SSIZE_MIN */
+int mpd_exp_digits(mpd_ssize_t exp);
+int mpd_iscanonical(const mpd_t *dec UNUSED);
+int mpd_isfinite(const mpd_t *dec);
+int mpd_isinfinite(const mpd_t *dec);
+int mpd_isinteger(const mpd_t *dec);
+int mpd_isnan(const mpd_t *dec);
+int mpd_isnegative(const mpd_t *dec);
+int mpd_ispositive(const mpd_t *dec);
+int mpd_isqnan(const mpd_t *dec);
+int mpd_issigned(const mpd_t *dec);
+int mpd_issnan(const mpd_t *dec);
+int mpd_isspecial(const mpd_t *dec);
+int mpd_iszero(const mpd_t *dec);
+/* undefined for special numbers */
+int mpd_iszerocoeff(const mpd_t *dec);
+int mpd_isnormal(const mpd_t *dec, const mpd_context_t *ctx);
+int mpd_issubnormal(const mpd_t *dec, const mpd_context_t *ctx);
+/* odd word */
+int mpd_isoddword(mpd_uint_t word);
+/* odd coefficient */
+int mpd_isoddcoeff(const mpd_t *dec);
+/* odd decimal, only defined for integers */
+int mpd_isodd(const mpd_t *dec);
+/* even decimal, only defined for integers */
+int mpd_iseven(const mpd_t *dec);
+/* 0 if dec is positive, 1 if dec is negative */
+uint8_t mpd_sign(const mpd_t *dec);
+/* 1 if dec is positive, -1 if dec is negative */
+int mpd_arith_sign(const mpd_t *dec);
+long mpd_radix(void);
+int mpd_isdynamic(mpd_t *dec);
+int mpd_isstatic(mpd_t *dec);
+int mpd_isdynamic_data(mpd_t *dec);
+int mpd_isstatic_data(mpd_t *dec);
+int mpd_isshared_data(mpd_t *dec);
+int mpd_isconst_data(mpd_t *dec);
+mpd_ssize_t mpd_trail_zeros(const mpd_t *dec);
+
+
+/******************************************************************************/
+/*                       Set attributes of a decimal                          */
+/******************************************************************************/
+
+/* set number of decimal digits in the coefficient */
+void mpd_setdigits(mpd_t *result);
+void mpd_set_sign(mpd_t *result, uint8_t sign);
+/* copy sign from another decimal */
+void mpd_signcpy(mpd_t *result, mpd_t *a);
+void mpd_set_infinity(mpd_t *result);
+void mpd_set_qnan(mpd_t *result);
+void mpd_set_snan(mpd_t *result);
+void mpd_set_negative(mpd_t *result);
+void mpd_set_positive(mpd_t *result);
+void mpd_set_dynamic(mpd_t *result);
+void mpd_set_static(mpd_t *result);
+void mpd_set_dynamic_data(mpd_t *result);
+void mpd_set_static_data(mpd_t *result);
+void mpd_set_shared_data(mpd_t *result);
+void mpd_set_const_data(mpd_t *result);
+void mpd_clear_flags(mpd_t *result);
+void mpd_set_flags(mpd_t *result, uint8_t flags);
+void mpd_copy_flags(mpd_t *result, const mpd_t *a);
+
+
+/******************************************************************************/
+/*                              Error Macros                                  */
+/******************************************************************************/
+
+#define mpd_err_fatal(...) \
+        do {fprintf(stderr, "%s:%d: error: ", __FILE__, __LINE__); \
+            fprintf(stderr, __VA_ARGS__);  fputc('\n', stderr); \
+            exit(1); \
+        } while (0)
+#define mpd_err_warn(...) \
+        do {fprintf(stderr, "%s:%d: warning: ", __FILE__, __LINE__); \
+            fprintf(stderr, __VA_ARGS__); fputc('\n', stderr); \
+        } while (0)
+
+
+/******************************************************************************/
+/*                            Memory handling                                 */
+/******************************************************************************/
+
+extern void *(* mpd_mallocfunc)(size_t size);
+extern void *(* mpd_callocfunc)(size_t nmemb, size_t size);
+extern void *(* mpd_reallocfunc)(void *ptr, size_t size);
+extern void (* mpd_free)(void *ptr);
+
+void *mpd_callocfunc_em(size_t nmemb, size_t size);
+
+void *mpd_alloc(mpd_size_t nmemb, mpd_size_t size);
+void *mpd_calloc(mpd_size_t nmemb, mpd_size_t size);
+void *mpd_realloc(void *ptr, mpd_size_t nmemb, mpd_size_t size, uint8_t *err);
+void *mpd_sh_alloc(mpd_size_t struct_size, mpd_size_t nmemb, mpd_size_t size);
+
+mpd_t *mpd_qnew(void);
+mpd_t *mpd_new(mpd_context_t *ctx);
+mpd_t *mpd_qnew_size(mpd_ssize_t size);
+void mpd_del(mpd_t *dec);
+
+void mpd_uint_zero(mpd_uint_t *dest, mpd_size_t len);
+int mpd_qresize(mpd_t *result, mpd_ssize_t size, uint32_t *status);
+int mpd_qresize_zero(mpd_t *result, mpd_ssize_t size, uint32_t *status);
+void mpd_minalloc(mpd_t *result);
+
+int mpd_resize(mpd_t *result, mpd_ssize_t size, mpd_context_t *ctx);
+int mpd_resize_zero(mpd_t *result, mpd_ssize_t size, mpd_context_t *ctx);
+
+
+#ifdef __cplusplus
+} /* END extern "C" */
+#endif
+
+
+#endif /* MPDECIMAL_64_H */
+
+
+

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 314 - 288
mpdecimal/mpdecimal.c


+ 136 - 0
mpdecimal/mpdecimal.depend

@@ -223,3 +223,139 @@
 	<string.h>
 	<signal.h>
 
+1328128189 source:/home/mingo/dev/SquiLu/mpdecimal/basearith.c
+	"mpdecimal.h"
+	<stdio.h>
+	<stdlib.h>
+	<string.h>
+	<assert.h>
+	"constants.h"
+	"memory.h"
+	"typearith.h"
+	"basearith.h"
+
+1358964297 /home/mingo/dev/SquiLu/mpdecimal/mpdecimal.h
+	<stdio.h>
+	<stdlib.h>
+	<string.h>
+	<limits.h>
+	<assert.h>
+	<stdint.h>
+
+1328128189 /home/mingo/dev/SquiLu/mpdecimal/constants.h
+	"mpdecimal.h"
+
+1328128189 /home/mingo/dev/SquiLu/mpdecimal/memory.h
+	"mpdecimal.h"
+
+1328128189 /home/mingo/dev/SquiLu/mpdecimal/typearith.h
+	"mpdecimal.h"
+	<intrin.h>
+
+1328128189 /home/mingo/dev/SquiLu/mpdecimal/basearith.h
+	"mpdecimal.h"
+	<stdio.h>
+	"typearith.h"
+
+1328128189 source:/home/mingo/dev/SquiLu/mpdecimal/constants.c
+	"mpdecimal.h"
+	<stdio.h>
+	"constants.h"
+
+1362948212 source:/home/mingo/dev/SquiLu/mpdecimal/context.c
+	"mpdecimal.h"
+	<stdio.h>
+	<string.h>
+	<signal.h>
+
+1328128189 source:/home/mingo/dev/SquiLu/mpdecimal/convolute.c
+	"mpdecimal.h"
+	<stdio.h>
+	"bits.h"
+	"constants.h"
+	"fnt.h"
+	"fourstep.h"
+	"numbertheory.h"
+	"sixstep.h"
+	"umodarith.h"
+	"convolute.h"
+
+1328128189 /home/mingo/dev/SquiLu/mpdecimal/bits.h
+	"mpdecimal.h"
+	<stdio.h>
+	<intrin.h>
+
+1328128189 /home/mingo/dev/SquiLu/mpdecimal/fnt.h
+	"mpdecimal.h"
+	<stdio.h>
+
+1328128189 /home/mingo/dev/SquiLu/mpdecimal/fourstep.h
+	"mpdecimal.h"
+	<stdio.h>
+
+1328128189 /home/mingo/dev/SquiLu/mpdecimal/numbertheory.h
+	"constants.h"
+	"mpdecimal.h"
+
+1328128189 /home/mingo/dev/SquiLu/mpdecimal/sixstep.h
+	"mpdecimal.h"
+	<stdio.h>
+
+1328128189 /home/mingo/dev/SquiLu/mpdecimal/umodarith.h
+	"constants.h"
+	"mpdecimal.h"
+	"typearith.h"
+
+1328128189 /home/mingo/dev/SquiLu/mpdecimal/convolute.h
+	"mpdecimal.h"
+	<stdio.h>
+
+1328128189 source:/home/mingo/dev/SquiLu/mpdecimal/crt.c
+	"mpdecimal.h"
+	<stdio.h>
+	<assert.h>
+	"numbertheory.h"
+	"umodarith.h"
+	"crt.h"
+
+1328128189 /home/mingo/dev/SquiLu/mpdecimal/crt.h
+	"mpdecimal.h"
+	<stdio.h>
+
+1328128189 source:/home/mingo/dev/SquiLu/mpdecimal/difradix2.c
+	"mpdecimal.h"
+	<stdio.h>
+	<assert.h>
+	"bits.h"
+	"numbertheory.h"
+	"umodarith.h"
+	"difradix2.h"
+
+1328128189 /home/mingo/dev/SquiLu/mpdecimal/difradix2.h
+	"mpdecimal.h"
+	<stdio.h>
+	"numbertheory.h"
+
+1328128189 source:/home/mingo/dev/SquiLu/mpdecimal/fnt.c
+	"mpdecimal.h"
+	<stdio.h>
+	<stdlib.h>
+	<assert.h>
+	"bits.h"
+	"difradix2.h"
+	"numbertheory.h"
+	"fnt.h"
+
+1328128189 source:/home/mingo/dev/SquiLu/mpdecimal/fourstep.c
+	"mpdecimal.h"
+	<assert.h>
+	"numbertheory.h"
+	"sixstep.h"
+	"transpose.h"
+	"umodarith.h"
+	"fourstep.h"
+
+1328128189 /home/mingo/dev/SquiLu/mpdecimal/transpose.h
+	"mpdecimal.h"
+	<stdio.h>
+

+ 769 - 6
mpdecimal/mpdecimal.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2010 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -29,21 +29,784 @@
 #ifndef MPDECIMAL_H
 #define MPDECIMAL_H
 
+
 #ifdef __cplusplus
 extern "C" {
-#define __STDC_LIMIT_MACROS
+  #ifndef __STDC_LIMIT_MACROS
+    #define __STDC_LIMIT_MACROS
+    #define MPD_CLEAR_STDC_LIMIT_MACROS
+  #endif
 #endif
 
-#ifdef CONFIG_64
-  #include "mpdecimal.64.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <assert.h>
+#include <stdint.h>
+#include <inttypes.h>
+
+
+#ifndef __GNUC_STDC_INLINE__
+  #define __GNUC_STDC_INLINE__ 1
+#endif
+#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
+  #define UNUSED __attribute__((unused))
+#else
+  #define UNUSED
+#endif
+#if (defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__)) && \
+    defined(__GNUC__) && __GNUC__ >= 4 && !defined(__INTEL_COMPILER)
+  #define MPD_PRAGMA(x) _Pragma(x)
+  #define MPD_HIDE_SYMBOLS_START "GCC visibility push(hidden)"
+  #define MPD_HIDE_SYMBOLS_END "GCC visibility pop"
 #else
-  #define CONFIG_32
-  #include "mpdecimal.32.h"
+  #define MPD_PRAGMA(x)
+  #define MPD_HIDE_SYMBOLS_START
+  #define MPD_HIDE_SYMBOLS_END
+#endif
+
+
+#if !defined(LEGACY_COMPILER)
+  #if !defined(UINT64_MAX)
+    /* The following #error is just a warning. If the compiler indeed does
+     * not have uint64_t, it is perfectly safe to comment out the #error. */
+    #error "Warning: Compiler without uint64_t. Comment out this line."
+    #define LEGACY_COMPILER
+  #endif
+#endif
+
+
+/******************************************************************************/
+/*                                  Version                                   */
+/******************************************************************************/
+
+#define MPD_MAJOR_VERSION 2
+#define MPD_MINOR_VERSION 4
+#define MPD_MICRO_VERSION 1
+
+#define MPD_VERSION "2.4.1"
+
+#define MPD_VERSION_HEX ((MPD_MAJOR_VERSION << 24) | \
+                         (MPD_MINOR_VERSION << 16) | \
+                         (MPD_MICRO_VERSION <<  8))
+
+const char *mpd_version(void);
+
+
+/******************************************************************************/
+/*                              Configuration                                 */
+/******************************************************************************/
+
+/* ABI: 64-bit */
+#ifdef CONFIG_32
+  #error "cannot use CONFIG_32 with 64-bit header."
+#endif
+
+#ifndef CONFIG_64
+  #define CONFIG_64
+#endif
+
+
+/* BEGIN CONFIG_64 */
+#if defined(CONFIG_64)
+/* types for modular and base arithmetic */
+#define MPD_UINT_MAX UINT64_MAX
+#define MPD_BITS_PER_UINT 64
+typedef uint64_t mpd_uint_t;  /* unsigned mod type */
+
+#define MPD_SIZE_MAX SIZE_MAX
+typedef size_t mpd_size_t; /* unsigned size type */
+
+/* type for exp, digits, len, prec */
+#define MPD_SSIZE_MAX INT64_MAX
+#define MPD_SSIZE_MIN INT64_MIN
+typedef int64_t mpd_ssize_t;
+#define _mpd_strtossize strtoll
+
+/* decimal arithmetic */
+#define MPD_RADIX 10000000000000000000ULL  /* 10**19 */
+#define MPD_RDIGITS 19
+#define MPD_MAX_POW10 19
+#define MPD_EXPDIGITS 19  /* MPD_EXPDIGITS <= MPD_RDIGITS+1 */
+
+#define MPD_MAXTRANSFORM_2N 4294967296ULL      /* 2**32 */
+#define MPD_MAX_PREC 999999999999999999LL
+#define MPD_MAX_PREC_LOG2 64
+#define MPD_ELIMIT  1000000000000000000LL
+#define MPD_MAX_EMAX   999999999999999999LL    /* ELIMIT-1 */
+#define MPD_MIN_EMIN  (-999999999999999999LL)  /* -EMAX */
+#define MPD_MIN_ETINY (MPD_MIN_EMIN-(MPD_MAX_PREC-1))
+#define MPD_EXP_INF 2000000000000000001LL
+#define MPD_EXP_CLAMP (-4000000000000000001LL)
+#define MPD_MAXIMPORT 105263157894736842L /* ceil((2*MPD_MAX_PREC)/MPD_RDIGITS) */
+
+/* conversion specifiers */
+#define PRI_mpd_uint_t PRIu64
+#define PRI_mpd_ssize_t PRIi64
+/* END CONFIG_64 */
+
+
+/* BEGIN CONFIG_32 */
+#elif defined(CONFIG_32)
+/* types for modular and base arithmetic */
+#define MPD_UINT_MAX UINT32_MAX
+#define MPD_BITS_PER_UINT 32
+typedef uint32_t mpd_uint_t;  /* unsigned mod type */
+
+#ifndef LEGACY_COMPILER
+#define MPD_UUINT_MAX UINT64_MAX
+typedef uint64_t mpd_uuint_t; /* double width unsigned mod type */
+#endif
+
+#define MPD_SIZE_MAX SIZE_MAX
+typedef size_t mpd_size_t; /* unsigned size type */
+
+/* type for dec->len, dec->exp, ctx->prec */
+#define MPD_SSIZE_MAX INT32_MAX
+#define MPD_SSIZE_MIN INT32_MIN
+typedef int32_t mpd_ssize_t;
+#define _mpd_strtossize strtol
+
+/* decimal arithmetic */
+#define MPD_RADIX 1000000000UL  /* 10**9 */
+#define MPD_RDIGITS 9
+#define MPD_MAX_POW10 9
+#define MPD_EXPDIGITS 10 /* MPD_EXPDIGITS <= MPD_RDIGITS+1 */
+
+#define MPD_MAXTRANSFORM_2N 33554432UL /* 2**25 */
+#define MPD_MAX_PREC 425000000L
+#define MPD_MAX_PREC_LOG2 32
+#define MPD_ELIMIT 425000001L
+#define MPD_MAX_EMAX 425000000L        /* ELIMIT-1 */
+#define MPD_MIN_EMIN (-425000000L)     /* -EMAX */
+#define MPD_MIN_ETINY (MPD_MIN_EMIN-(MPD_MAX_PREC-1))
+#define MPD_EXP_INF 1000000001L      /* allows for emax=999999999 in the tests */
+#define MPD_EXP_CLAMP (-2000000001L) /* allows for emin=-999999999 in the tests */
+#define MPD_MAXIMPORT 94444445L      /* ceil((2*MPD_MAX_PREC)/MPD_RDIGITS) */
+
+/* conversion specifiers */
+#define PRI_mpd_uint_t PRIu32
+#define PRI_mpd_ssize_t PRIi32
+/* END CONFIG_32 */
+
+#else
+  #error "define CONFIG_64 or CONFIG_32"
+#endif
+/* END CONFIG */
+
+
+#if MPD_SIZE_MAX != MPD_UINT_MAX
+  #error "unsupported platform: need mpd_size_t == mpd_uint_t"
+#endif
+
+
+/******************************************************************************/
+/*                                Context                                     */
+/******************************************************************************/
+
+enum {
+    MPD_ROUND_UP,          /* round away from 0               */
+    MPD_ROUND_DOWN,        /* round toward 0 (truncate)       */
+    MPD_ROUND_CEILING,     /* round toward +infinity          */
+    MPD_ROUND_FLOOR,       /* round toward -infinity          */
+    MPD_ROUND_HALF_UP,     /* 0.5 is rounded up               */
+    MPD_ROUND_HALF_DOWN,   /* 0.5 is rounded down             */
+    MPD_ROUND_HALF_EVEN,   /* 0.5 is rounded to even          */
+    MPD_ROUND_05UP,        /* round zero or five away from 0  */
+    MPD_ROUND_TRUNC,       /* truncate, but set infinity      */
+    MPD_ROUND_GUARD
+};
+
+enum { MPD_CLAMP_DEFAULT, MPD_CLAMP_IEEE_754, MPD_CLAMP_GUARD };
+
+extern const char *mpd_round_string[MPD_ROUND_GUARD];
+extern const char *mpd_clamp_string[MPD_CLAMP_GUARD];
+
+
+typedef struct mpd_context_t {
+    mpd_ssize_t prec;   /* precision */
+    mpd_ssize_t emax;   /* max positive exp */
+    mpd_ssize_t emin;   /* min negative exp */
+    uint32_t traps;     /* status events that should be trapped */
+    uint32_t status;    /* status flags */
+    uint32_t newtrap;   /* set by mpd_addstatus_raise() */
+    int      round;     /* rounding mode */
+    int      clamp;     /* clamp mode */
+    int      allcr;     /* all functions correctly rounded */
+} mpd_context_t;
+
+
+/* Status flags */
+#define MPD_Clamped             0x00000001U
+#define MPD_Conversion_syntax   0x00000002U
+#define MPD_Division_by_zero    0x00000004U
+#define MPD_Division_impossible 0x00000008U
+#define MPD_Division_undefined  0x00000010U
+#define MPD_Fpu_error           0x00000020U
+#define MPD_Inexact             0x00000040U
+#define MPD_Invalid_context     0x00000080U
+#define MPD_Invalid_operation   0x00000100U
+#define MPD_Malloc_error        0x00000200U
+#define MPD_Not_implemented     0x00000400U
+#define MPD_Overflow            0x00000800U
+#define MPD_Rounded             0x00001000U
+#define MPD_Subnormal           0x00002000U
+#define MPD_Underflow           0x00004000U
+#define MPD_Max_status         (0x00008000U-1U)
+
+/* Conditions that result in an IEEE 754 exception */
+#define MPD_IEEE_Invalid_operation (MPD_Conversion_syntax |   \
+                                    MPD_Division_impossible | \
+                                    MPD_Division_undefined |  \
+                                    MPD_Fpu_error |           \
+                                    MPD_Invalid_context |     \
+                                    MPD_Invalid_operation |   \
+                                    MPD_Malloc_error)         \
+
+/* Errors that require the result of an operation to be set to NaN */
+#define MPD_Errors (MPD_IEEE_Invalid_operation | \
+                    MPD_Division_by_zero)
+
+/* Default traps */
+#define MPD_Traps (MPD_IEEE_Invalid_operation | \
+                   MPD_Division_by_zero |       \
+                   MPD_Overflow |               \
+                   MPD_Underflow)
+
+/* Official name */
+#define MPD_Insufficient_storage MPD_Malloc_error
+
+/* IEEE 754 interchange format contexts */
+#define MPD_IEEE_CONTEXT_MAX_BITS 512 /* 16*(log2(MPD_MAX_EMAX / 3)-3) */
+#define MPD_DECIMAL32 32
+#define MPD_DECIMAL64 64
+#define MPD_DECIMAL128 128
+
+
+#define MPD_MINALLOC_MIN 2
+#define MPD_MINALLOC_MAX 64
+extern mpd_ssize_t MPD_MINALLOC;
+extern void (* mpd_traphandler)(mpd_context_t *);
+void mpd_dflt_traphandler(mpd_context_t *);
+
+void mpd_setminalloc(mpd_ssize_t n);
+void mpd_init(mpd_context_t *ctx, mpd_ssize_t prec);
+
+void mpd_maxcontext(mpd_context_t *ctx);
+void mpd_defaultcontext(mpd_context_t *ctx);
+void mpd_basiccontext(mpd_context_t *ctx);
+int mpd_ieee_context(mpd_context_t *ctx, int bits);
+
+mpd_ssize_t mpd_getprec(const mpd_context_t *ctx);
+mpd_ssize_t mpd_getemax(const mpd_context_t *ctx);
+mpd_ssize_t mpd_getemin(const mpd_context_t *ctx);
+int mpd_getround(const mpd_context_t *ctx);
+uint32_t mpd_gettraps(const mpd_context_t *ctx);
+uint32_t mpd_getstatus(const mpd_context_t *ctx);
+int mpd_getclamp(const mpd_context_t *ctx);
+int mpd_getcr(const mpd_context_t *ctx);
+
+int mpd_qsetprec(mpd_context_t *ctx, mpd_ssize_t prec);
+int mpd_qsetemax(mpd_context_t *ctx, mpd_ssize_t emax);
+int mpd_qsetemin(mpd_context_t *ctx, mpd_ssize_t emin);
+int mpd_qsetround(mpd_context_t *ctx, int newround);
+int mpd_qsettraps(mpd_context_t *ctx, uint32_t flags);
+int mpd_qsetstatus(mpd_context_t *ctx, uint32_t flags);
+int mpd_qsetclamp(mpd_context_t *ctx, int c);
+int mpd_qsetcr(mpd_context_t *ctx, int c);
+void mpd_addstatus_raise(mpd_context_t *ctx, uint32_t flags);
+
+
+/******************************************************************************/
+/*                           Decimal Arithmetic                               */
+/******************************************************************************/
+
+/* mpd_t flags */
+#define MPD_POS                 ((uint8_t)0)
+#define MPD_NEG                 ((uint8_t)1)
+#define MPD_INF                 ((uint8_t)2)
+#define MPD_NAN                 ((uint8_t)4)
+#define MPD_SNAN                ((uint8_t)8)
+#define MPD_SPECIAL (MPD_INF|MPD_NAN|MPD_SNAN)
+#define MPD_STATIC              ((uint8_t)16)
+#define MPD_STATIC_DATA         ((uint8_t)32)
+#define MPD_SHARED_DATA         ((uint8_t)64)
+#define MPD_CONST_DATA          ((uint8_t)128)
+#define MPD_DATAFLAGS (MPD_STATIC_DATA|MPD_SHARED_DATA|MPD_CONST_DATA)
+
+/* mpd_t */
+typedef struct mpd_t {
+    uint8_t flags;
+    mpd_ssize_t exp;
+    mpd_ssize_t digits;
+    mpd_ssize_t len;
+    mpd_ssize_t alloc;
+    mpd_uint_t *data;
+} mpd_t;
+
+
+typedef unsigned char uchar;
+
+
+/******************************************************************************/
+/*                       Quiet, thread-safe functions                         */
+/******************************************************************************/
+
+/* format specification */
+typedef struct mpd_spec_t {
+    mpd_ssize_t min_width; /* minimum field width */
+    mpd_ssize_t prec;      /* fraction digits or significant digits */
+    char type;             /* conversion specifier */
+    char align;            /* alignment */
+    char sign;             /* sign printing/alignment */
+    char fill[5];          /* fill character */
+    const char *dot;       /* decimal point */
+    const char *sep;       /* thousands separator */
+    const char *grouping;  /* grouping of digits */
+} mpd_spec_t;
+
+/* output to a string */
+char *mpd_to_sci(const mpd_t *dec, int fmt);
+char *mpd_to_eng(const mpd_t *dec, int fmt);
+mpd_ssize_t mpd_to_sci_size(char **res, const mpd_t *dec, int fmt);
+mpd_ssize_t mpd_to_eng_size(char **res, const mpd_t *dec, int fmt);
+int mpd_validate_lconv(mpd_spec_t *spec);
+int mpd_parse_fmt_str(mpd_spec_t *spec, const char *fmt, int caps);
+char *mpd_qformat_spec(const mpd_t *dec, const mpd_spec_t *spec, const mpd_context_t *ctx, uint32_t *status);
+char *mpd_qformat(const mpd_t *dec, const char *fmt, const mpd_context_t *ctx, uint32_t *status);
+
+#define MPD_NUM_FLAGS 15
+#define MPD_MAX_FLAG_STRING 208
+#define MPD_MAX_FLAG_LIST (MPD_MAX_FLAG_STRING+18)
+#define MPD_MAX_SIGNAL_LIST 121
+int mpd_snprint_flags(char *dest, int nmemb, uint32_t flags);
+int mpd_lsnprint_flags(char *dest, int nmemb, uint32_t flags, const char *flag_string[]);
+int mpd_lsnprint_signals(char *dest, int nmemb, uint32_t flags, const char *signal_string[]);
+
+/* output to a file */
+void mpd_fprint(FILE *file, const mpd_t *dec);
+void mpd_print(const mpd_t *dec);
+
+/* assignment from a string */
+void mpd_qset_string(mpd_t *dec, const char *s, const mpd_context_t *ctx, uint32_t *status);
+
+/* set to NaN with error flags */
+void mpd_seterror(mpd_t *result, uint32_t flags, uint32_t *status);
+/* set a special with sign and type */
+void mpd_setspecial(mpd_t *dec, uint8_t sign, uint8_t type);
+/* set coefficient to zero or all nines */
+void mpd_zerocoeff(mpd_t *result);
+void mpd_qmaxcoeff(mpd_t *result, const mpd_context_t *ctx, uint32_t *status);
+
+/* quietly assign a C integer type to an mpd_t */
+void mpd_qset_ssize(mpd_t *result, mpd_ssize_t a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qset_i32(mpd_t *result, int32_t a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qset_uint(mpd_t *result, mpd_uint_t a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qset_u32(mpd_t *result, uint32_t a, const mpd_context_t *ctx, uint32_t *status);
+#ifndef LEGACY_COMPILER
+void mpd_qset_i64(mpd_t *result, int64_t a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qset_u64(mpd_t *result, uint64_t a, const mpd_context_t *ctx, uint32_t *status);
 #endif
 
+/* quietly assign a C integer type to an mpd_t with a static coefficient */
+void mpd_qsset_ssize(mpd_t *result, mpd_ssize_t a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qsset_i32(mpd_t *result, int32_t a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qsset_uint(mpd_t *result, mpd_uint_t a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qsset_u32(mpd_t *result, uint32_t a, const mpd_context_t *ctx, uint32_t *status);
+
+/* quietly get a C integer type from an mpd_t */
+mpd_ssize_t mpd_qget_ssize(const mpd_t *dec, uint32_t *status);
+mpd_uint_t mpd_qget_uint(const mpd_t *dec, uint32_t *status);
+mpd_uint_t mpd_qabs_uint(const mpd_t *dec, uint32_t *status);
+
+int32_t mpd_qget_i32(const mpd_t *dec, uint32_t *status);
+uint32_t mpd_qget_u32(const mpd_t *dec, uint32_t *status);
+#ifndef LEGACY_COMPILER
+int64_t mpd_qget_i64(const mpd_t *dec, uint32_t *status);
+uint64_t mpd_qget_u64(const mpd_t *dec, uint32_t *status);
+#endif
+
+/* quiet functions */
+int mpd_qcheck_nan(mpd_t *nanresult, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+int mpd_qcheck_nans(mpd_t *nanresult, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qfinalize(mpd_t *result, const mpd_context_t *ctx, uint32_t *status);
+
+const char *mpd_class(const mpd_t *a, const mpd_context_t *ctx);
+
+int mpd_qcopy(mpd_t *result, const mpd_t *a,  uint32_t *status);
+mpd_t *mpd_qncopy(const mpd_t *a);
+int mpd_qcopy_abs(mpd_t *result, const mpd_t *a, uint32_t *status);
+int mpd_qcopy_negate(mpd_t *result, const mpd_t *a, uint32_t *status);
+int mpd_qcopy_sign(mpd_t *result, const mpd_t *a, const mpd_t *b, uint32_t *status);
+
+void mpd_qand(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qinvert(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qlogb(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qor(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qscaleb(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qxor(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+int mpd_same_quantum(const mpd_t *a, const mpd_t *b);
+
+void mpd_qrotate(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+int mpd_qshiftl(mpd_t *result, const mpd_t *a, mpd_ssize_t n, uint32_t *status);
+mpd_uint_t mpd_qshiftr(mpd_t *result, const mpd_t *a, mpd_ssize_t n, uint32_t *status);
+mpd_uint_t mpd_qshiftr_inplace(mpd_t *result, mpd_ssize_t n);
+void mpd_qshift(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qshiftn(mpd_t *result, const mpd_t *a, mpd_ssize_t n, const mpd_context_t *ctx, uint32_t *status);
+
+int mpd_qcmp(const mpd_t *a, const mpd_t *b, uint32_t *status);
+int mpd_qcompare(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+int mpd_qcompare_signal(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+int mpd_cmp_total(const mpd_t *a, const mpd_t *b);
+int mpd_cmp_total_mag(const mpd_t *a, const mpd_t *b);
+int mpd_compare_total(mpd_t *result, const mpd_t *a, const mpd_t *b);
+int mpd_compare_total_mag(mpd_t *result, const mpd_t *a, const mpd_t *b);
+
+void mpd_qround_to_intx(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qround_to_int(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qtrunc(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qfloor(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qceil(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+
+void mpd_qabs(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qmax(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qmax_mag(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qmin(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qmin_mag(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qminus(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qplus(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qnext_minus(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qnext_plus(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qnext_toward(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qquantize(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qrescale(mpd_t *result, const mpd_t *a, mpd_ssize_t exp, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qrescale_fmt(mpd_t *result, const mpd_t *a, mpd_ssize_t exp, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qreduce(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qadd(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qadd_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qadd_i32(mpd_t *result, const mpd_t *a, int32_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qadd_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qadd_u32(mpd_t *result, const mpd_t *a, uint32_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qsub(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qsub_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qsub_i32(mpd_t *result, const mpd_t *a, int32_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qsub_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qsub_u32(mpd_t *result, const mpd_t *a, uint32_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qmul(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qmul_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qmul_i32(mpd_t *result, const mpd_t *a, int32_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qmul_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qmul_u32(mpd_t *result, const mpd_t *a, uint32_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qfma(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_t *c, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qdiv(mpd_t *q, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qdiv_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qdiv_i32(mpd_t *result, const mpd_t *a, int32_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qdiv_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qdiv_u32(mpd_t *result, const mpd_t *a, uint32_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qdivint(mpd_t *q, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qrem(mpd_t *r, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qrem_near(mpd_t *r, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qdivmod(mpd_t *q, mpd_t *r, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qpow(mpd_t *result, const mpd_t *base, const mpd_t *exp, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qpowmod(mpd_t *result, const mpd_t *base, const mpd_t *exp, const mpd_t *mod, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qexp(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qln10(mpd_t *result, mpd_ssize_t prec, uint32_t *status);
+void mpd_qln(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qlog10(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qsqrt(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qinvroot(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+
+#ifndef LEGACY_COMPILER
+void mpd_qadd_i64(mpd_t *result, const mpd_t *a, int64_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qadd_u64(mpd_t *result, const mpd_t *a, uint64_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qsub_i64(mpd_t *result, const mpd_t *a, int64_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qsub_u64(mpd_t *result, const mpd_t *a, uint64_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qmul_i64(mpd_t *result, const mpd_t *a, int64_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qmul_u64(mpd_t *result, const mpd_t *a, uint64_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qdiv_i64(mpd_t *result, const mpd_t *a, int64_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qdiv_u64(mpd_t *result, const mpd_t *a, uint64_t b, const mpd_context_t *ctx, uint32_t *status);
+#endif
+
+
+size_t mpd_sizeinbase(const mpd_t *a, uint32_t base);
+void mpd_qimport_u16(mpd_t *result, const uint16_t *srcdata, size_t srclen,
+                     uint8_t srcsign, uint32_t srcbase,
+                     const mpd_context_t *ctx, uint32_t *status);
+void mpd_qimport_u32(mpd_t *result, const uint32_t *srcdata, size_t srclen,
+                     uint8_t srcsign, uint32_t srcbase,
+                     const mpd_context_t *ctx, uint32_t *status);
+size_t mpd_qexport_u16(uint16_t **rdata, size_t rlen, uint32_t base,
+                       const mpd_t *src, uint32_t *status);
+size_t mpd_qexport_u32(uint32_t **rdata, size_t rlen, uint32_t base,
+                       const mpd_t *src, uint32_t *status);
+
+
+/******************************************************************************/
+/*                           Signalling functions                             */
+/******************************************************************************/
+
+char *mpd_format(const mpd_t *dec, const char *fmt, mpd_context_t *ctx);
+void mpd_import_u16(mpd_t *result, const uint16_t *srcdata, size_t srclen, uint8_t srcsign, uint32_t base, mpd_context_t *ctx);
+void mpd_import_u32(mpd_t *result, const uint32_t *srcdata, size_t srclen, uint8_t srcsign, uint32_t base, mpd_context_t *ctx);
+size_t mpd_export_u16(uint16_t **rdata, size_t rlen, uint32_t base, const mpd_t *src, mpd_context_t *ctx);
+size_t mpd_export_u32(uint32_t **rdata, size_t rlen, uint32_t base, const mpd_t *src, mpd_context_t *ctx);
+void mpd_finalize(mpd_t *result, mpd_context_t *ctx);
+int mpd_check_nan(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+int mpd_check_nans(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_set_string(mpd_t *result, const char *s, mpd_context_t *ctx);
+void mpd_maxcoeff(mpd_t *result, mpd_context_t *ctx);
+void mpd_sset_ssize(mpd_t *result, mpd_ssize_t a, mpd_context_t *ctx);
+void mpd_sset_i32(mpd_t *result, int32_t a, mpd_context_t *ctx);
+void mpd_sset_uint(mpd_t *result, mpd_uint_t a, mpd_context_t *ctx);
+void mpd_sset_u32(mpd_t *result, uint32_t a, mpd_context_t *ctx);
+void mpd_set_ssize(mpd_t *result, mpd_ssize_t a, mpd_context_t *ctx);
+void mpd_set_i32(mpd_t *result, int32_t a, mpd_context_t *ctx);
+void mpd_set_uint(mpd_t *result, mpd_uint_t a, mpd_context_t *ctx);
+void mpd_set_u32(mpd_t *result, uint32_t a, mpd_context_t *ctx);
+#ifndef LEGACY_COMPILER
+void mpd_set_i64(mpd_t *result, int64_t a, mpd_context_t *ctx);
+void mpd_set_u64(mpd_t *result, uint64_t a, mpd_context_t *ctx);
+#endif
+mpd_ssize_t mpd_get_ssize(const mpd_t *a, mpd_context_t *ctx);
+mpd_uint_t mpd_get_uint(const mpd_t *a, mpd_context_t *ctx);
+mpd_uint_t mpd_abs_uint(const mpd_t *a, mpd_context_t *ctx);
+int32_t mpd_get_i32(const mpd_t *a, mpd_context_t *ctx);
+uint32_t mpd_get_u32(const mpd_t *a, mpd_context_t *ctx);
+#ifndef LEGACY_COMPILER
+int64_t mpd_get_i64(const mpd_t *a, mpd_context_t *ctx);
+uint64_t mpd_get_u64(const mpd_t *a, mpd_context_t *ctx);
+#endif
+void mpd_and(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_copy(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_canonical(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_copy_abs(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_copy_negate(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_copy_sign(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_invert(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_logb(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_or(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_rotate(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_scaleb(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_shiftl(mpd_t *result, const mpd_t *a, mpd_ssize_t n, mpd_context_t *ctx);
+mpd_uint_t mpd_shiftr(mpd_t *result, const mpd_t *a, mpd_ssize_t n, mpd_context_t *ctx);
+void mpd_shiftn(mpd_t *result, const mpd_t *a, mpd_ssize_t n, mpd_context_t *ctx);
+void mpd_shift(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_xor(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_abs(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+int mpd_cmp(const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+int mpd_compare(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+int mpd_compare_signal(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_add(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_add_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, mpd_context_t *ctx);
+void mpd_add_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx);
+void mpd_add_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, mpd_context_t *ctx);
+void mpd_add_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx);
+void mpd_sub(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_sub_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, mpd_context_t *ctx);
+void mpd_sub_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx);
+void mpd_sub_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, mpd_context_t *ctx);
+void mpd_sub_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx);
+void mpd_div(mpd_t *q, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_div_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, mpd_context_t *ctx);
+void mpd_div_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx);
+void mpd_div_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, mpd_context_t *ctx);
+void mpd_div_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx);
+void mpd_divmod(mpd_t *q, mpd_t *r, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_divint(mpd_t *q, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_exp(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_fma(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_t *c, mpd_context_t *ctx);
+void mpd_ln(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_log10(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_max(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_max_mag(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_min(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_min_mag(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_minus(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_mul(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_mul_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, mpd_context_t *ctx);
+void mpd_mul_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx);
+void mpd_mul_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, mpd_context_t *ctx);
+void mpd_mul_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx);
+void mpd_next_minus(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_next_plus(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_next_toward(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_plus(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_pow(mpd_t *result, const mpd_t *base, const mpd_t *exp, mpd_context_t *ctx);
+void mpd_powmod(mpd_t *result, const mpd_t *base, const mpd_t *exp, const mpd_t *mod, mpd_context_t *ctx);
+void mpd_quantize(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_rescale(mpd_t *result, const mpd_t *a, mpd_ssize_t exp, mpd_context_t *ctx);
+void mpd_reduce(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_rem(mpd_t *r, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_rem_near(mpd_t *r, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_round_to_intx(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_round_to_int(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_trunc(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_floor(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_ceil(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_sqrt(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_invroot(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+
+#ifndef LEGACY_COMPILER
+void mpd_add_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx);
+void mpd_add_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx);
+void mpd_sub_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx);
+void mpd_sub_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx);
+void mpd_div_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx);
+void mpd_div_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx);
+void mpd_mul_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx);
+void mpd_mul_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx);
+#endif
+
+
+/******************************************************************************/
+/*                          Configuration specific                            */
+/******************************************************************************/
+
+#ifdef CONFIG_64
+void mpd_qsset_i64(mpd_t *result, int64_t a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qsset_u64(mpd_t *result, uint64_t a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_sset_i64(mpd_t *result, int64_t a, mpd_context_t *ctx);
+void mpd_sset_u64(mpd_t *result, uint64_t a, mpd_context_t *ctx);
+#endif
+
+
+/******************************************************************************/
+/*                       Get attributes of a decimal                          */
+/******************************************************************************/
+
+mpd_ssize_t mpd_adjexp(const mpd_t *dec);
+mpd_ssize_t mpd_etiny(const mpd_context_t *ctx);
+mpd_ssize_t mpd_etop(const mpd_context_t *ctx);
+mpd_uint_t mpd_msword(const mpd_t *dec);
+int mpd_word_digits(mpd_uint_t word);
+/* most significant digit of a word */
+mpd_uint_t mpd_msd(mpd_uint_t word);
+/* least significant digit of a word */
+mpd_uint_t mpd_lsd(mpd_uint_t word);
+/* coefficient size needed to store 'digits' */
+mpd_ssize_t mpd_digits_to_size(mpd_ssize_t digits);
+/* number of digits in the exponent, undefined for MPD_SSIZE_MIN */
+int mpd_exp_digits(mpd_ssize_t exp);
+int mpd_iscanonical(const mpd_t *dec UNUSED);
+int mpd_isfinite(const mpd_t *dec);
+int mpd_isinfinite(const mpd_t *dec);
+int mpd_isinteger(const mpd_t *dec);
+int mpd_isnan(const mpd_t *dec);
+int mpd_isnegative(const mpd_t *dec);
+int mpd_ispositive(const mpd_t *dec);
+int mpd_isqnan(const mpd_t *dec);
+int mpd_issigned(const mpd_t *dec);
+int mpd_issnan(const mpd_t *dec);
+int mpd_isspecial(const mpd_t *dec);
+int mpd_iszero(const mpd_t *dec);
+/* undefined for special numbers */
+int mpd_iszerocoeff(const mpd_t *dec);
+int mpd_isnormal(const mpd_t *dec, const mpd_context_t *ctx);
+int mpd_issubnormal(const mpd_t *dec, const mpd_context_t *ctx);
+/* odd word */
+int mpd_isoddword(mpd_uint_t word);
+/* odd coefficient */
+int mpd_isoddcoeff(const mpd_t *dec);
+/* odd decimal, only defined for integers */
+int mpd_isodd(const mpd_t *dec);
+/* even decimal, only defined for integers */
+int mpd_iseven(const mpd_t *dec);
+/* 0 if dec is positive, 1 if dec is negative */
+uint8_t mpd_sign(const mpd_t *dec);
+/* 1 if dec is positive, -1 if dec is negative */
+int mpd_arith_sign(const mpd_t *dec);
+long mpd_radix(void);
+int mpd_isdynamic(const mpd_t *dec);
+int mpd_isstatic(const mpd_t *dec);
+int mpd_isdynamic_data(const mpd_t *dec);
+int mpd_isstatic_data(const mpd_t *dec);
+int mpd_isshared_data(const mpd_t *dec);
+int mpd_isconst_data(const mpd_t *dec);
+mpd_ssize_t mpd_trail_zeros(const mpd_t *dec);
+
+
+/******************************************************************************/
+/*                       Set attributes of a decimal                          */
+/******************************************************************************/
+
+/* set number of decimal digits in the coefficient */
+void mpd_setdigits(mpd_t *result);
+void mpd_set_sign(mpd_t *result, uint8_t sign);
+/* copy sign from another decimal */
+void mpd_signcpy(mpd_t *result, const mpd_t *a);
+void mpd_set_infinity(mpd_t *result);
+void mpd_set_qnan(mpd_t *result);
+void mpd_set_snan(mpd_t *result);
+void mpd_set_negative(mpd_t *result);
+void mpd_set_positive(mpd_t *result);
+void mpd_set_dynamic(mpd_t *result);
+void mpd_set_static(mpd_t *result);
+void mpd_set_dynamic_data(mpd_t *result);
+void mpd_set_static_data(mpd_t *result);
+void mpd_set_shared_data(mpd_t *result);
+void mpd_set_const_data(mpd_t *result);
+void mpd_clear_flags(mpd_t *result);
+void mpd_set_flags(mpd_t *result, uint8_t flags);
+void mpd_copy_flags(mpd_t *result, const mpd_t *a);
+
+
+/******************************************************************************/
+/*                              Error Macros                                  */
+/******************************************************************************/
+
+#define mpd_err_fatal(...) \
+    do {fprintf(stderr, "%s:%d: error: ", __FILE__, __LINE__); \
+        fprintf(stderr, __VA_ARGS__);  fputc('\n', stderr);    \
+        abort();                                               \
+    } while (0)
+#define mpd_err_warn(...) \
+    do {fprintf(stderr, "%s:%d: warning: ", __FILE__, __LINE__); \
+        fprintf(stderr, __VA_ARGS__); fputc('\n', stderr);       \
+    } while (0)
+
+
+/******************************************************************************/
+/*                            Memory handling                                 */
+/******************************************************************************/
+
+extern void *(* mpd_mallocfunc)(size_t size);
+extern void *(* mpd_callocfunc)(size_t nmemb, size_t size);
+extern void *(* mpd_reallocfunc)(void *ptr, size_t size);
+extern void (* mpd_free)(void *ptr);
+
+void *mpd_callocfunc_em(size_t nmemb, size_t size);
+
+void *mpd_alloc(mpd_size_t nmemb, mpd_size_t size);
+void *mpd_calloc(mpd_size_t nmemb, mpd_size_t size);
+void *mpd_realloc(void *ptr, mpd_size_t nmemb, mpd_size_t size, uint8_t *err);
+void *mpd_sh_alloc(mpd_size_t struct_size, mpd_size_t nmemb, mpd_size_t size);
+
+mpd_t *mpd_qnew(void);
+mpd_t *mpd_new(mpd_context_t *ctx);
+mpd_t *mpd_qnew_size(mpd_ssize_t size);
+void mpd_del(mpd_t *dec);
+
+void mpd_uint_zero(mpd_uint_t *dest, mpd_size_t len);
+int mpd_qresize(mpd_t *result, mpd_ssize_t size, uint32_t *status);
+int mpd_qresize_zero(mpd_t *result, mpd_ssize_t size, uint32_t *status);
+void mpd_minalloc(mpd_t *result);
+
+int mpd_resize(mpd_t *result, mpd_ssize_t size, mpd_context_t *ctx);
+int mpd_resize_zero(mpd_t *result, mpd_ssize_t size, mpd_context_t *ctx);
+
+
 #ifdef __cplusplus
+  #ifdef MPD_CLEAR_STDC_LIMIT_MACROS
+    #undef MPD_CLEAR_STDC_LIMIT_MACROS
+    #undef __STDC_LIMIT_MACROS
+  #endif
 } /* END extern "C" */
 #endif
 
 
 #endif /* MPDECIMAL_H */
+
+
+

+ 24 - 12
mpdecimal/mpdecimal.layout

@@ -1,25 +1,37 @@
 <?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
 <CodeBlocks_layout_file>
-	<ActiveTarget name="Release win32" />
-	<File name="basearith.c" open="0" top="0" tabpos="0">
-		<Cursor position="1384" topLine="16" />
+	<ActiveTarget name="Release_64bits" />
+	<File name="constants.h" open="0" top="0" tabpos="0">
+		<Cursor position="1727" topLine="27" />
 	</File>
-	<File name="context.c" open="0" top="0" tabpos="6">
-		<Cursor position="5818" topLine="274" />
+	<File name="context.c" open="0" top="0" tabpos="4">
+		<Cursor position="0" topLine="0" />
 	</File>
 	<File name="convolute.c" open="0" top="0" tabpos="0">
-		<Cursor position="1530" topLine="23" />
+		<Cursor position="1906" topLine="39" />
 	</File>
-	<File name="io.c" open="0" top="0" tabpos="0">
-		<Cursor position="1646" topLine="28" />
+	<File name="crt.c" open="0" top="0" tabpos="0">
+		<Cursor position="4185" topLine="157" />
 	</File>
-	<File name="io.h" open="0" top="0" tabpos="0">
-		<Cursor position="0" topLine="33" />
+	<File name="io.c" open="0" top="0" tabpos="5">
+		<Cursor position="0" topLine="36" />
+	</File>
+	<File name="io.h" open="0" top="0" tabpos="7">
+		<Cursor position="1373" topLine="15" />
+	</File>
+	<File name="memory.h" open="0" top="0" tabpos="0">
+		<Cursor position="0" topLine="13" />
+	</File>
+	<File name="mpdecimal.32.h" open="0" top="0" tabpos="0">
+		<Cursor position="4736" topLine="136" />
+	</File>
+	<File name="mpdecimal.64.h" open="0" top="0" tabpos="0">
+		<Cursor position="2076" topLine="47" />
 	</File>
 	<File name="mpdecimal.c" open="0" top="0" tabpos="4">
-		<Cursor position="73866" topLine="24" />
+		<Cursor position="0" topLine="0" />
 	</File>
 	<File name="mpdecimal.h" open="0" top="0" tabpos="0">
-		<Cursor position="7068" topLine="188" />
+		<Cursor position="1576" topLine="17" />
 	</File>
 </CodeBlocks_layout_file>

+ 731 - 0
mpdecimal/mpdecimal32vc.h

@@ -0,0 +1,731 @@
+/*
+ * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#ifndef MPDECIMAL_H
+#define MPDECIMAL_H
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <assert.h>
+
+#include "vccompat.h"
+#ifndef UNUSED
+  #define UNUSED
+#endif
+#define MPD_PRAGMA(x)
+#define MPD_HIDE_SYMBOLS_START
+#define MPD_HIDE_SYMBOLS_END
+#define EXTINLINE extern inline
+
+#define IMPORTEXPORT
+
+#if defined (BUILD_DLL)
+  #undef IMPORTEXPORT
+  #define IMPORTEXPORT __declspec( dllexport )
+#elif defined (USE_DLL)
+  #undef IMPORTEXPORT
+  #define IMPORTEXPORT __declspec( dllimport )
+#endif
+
+
+#if !defined(LEGACY_COMPILER)
+  #if !defined(UINT64_MAX)
+    /* The following #error is just a warning. If the compiler indeed does
+     * not have uint64_t, it is perfectly safe to comment out the #error. */
+    #error "Warning: Compiler without uint64_t. Comment out this line."
+    #define LEGACY_COMPILER
+  #endif
+#endif
+
+
+/******************************************************************************/
+/*                                  Version                                   */
+/******************************************************************************/
+
+#define MPD_MAJOR_VERSION 2
+#define MPD_MINOR_VERSION 4
+#define MPD_MICRO_VERSION 1
+
+#define MPD_VERSION "2.4.1"
+
+#define MPD_VERSION_HEX ((MPD_MAJOR_VERSION << 24) | \
+                         (MPD_MINOR_VERSION << 16) | \
+                         (MPD_MICRO_VERSION <<  8))
+
+IMPORTEXPORT const char *mpd_version(void);
+
+
+/******************************************************************************/
+/*                      Types for 32 bit architectures                        */
+/******************************************************************************/
+
+/* types for modular and base arithmetic */
+#define MPD_UINT_MAX UINT32_MAX
+#define MPD_BITS_PER_UINT 32
+typedef uint32_t mpd_uint_t;  /* unsigned mod type */
+
+#ifndef LEGACY_COMPILER
+#define MPD_UUINT_MAX UINT64_MAX
+typedef uint64_t mpd_uuint_t; /* double width unsigned mod type */
+#endif
+
+#define MPD_SIZE_MAX SIZE_MAX
+typedef size_t mpd_size_t; /* unsigned size type */
+
+/* type for dec->len, dec->exp, ctx->prec */
+#define MPD_SSIZE_MAX INT32_MAX
+#define MPD_SSIZE_MIN INT32_MIN
+typedef int32_t mpd_ssize_t;
+#define _mpd_strtossize strtol
+
+/* decimal arithmetic */
+#define MPD_RADIX 1000000000UL  /* 10**9 */
+#define MPD_RDIGITS 9
+#define MPD_MAX_POW10 9
+#define MPD_EXPDIGITS 10 /* MPD_EXPDIGITS <= MPD_RDIGITS+1 */
+
+#define MPD_MAXTRANSFORM_2N 33554432UL /* 2**25 */
+#define MPD_MAX_PREC 425000000L
+#define MPD_MAX_PREC_LOG2 32
+#define MPD_ELIMIT 425000001L
+#define MPD_MAX_EMAX 425000000L        /* ELIMIT-1 */
+#define MPD_MIN_EMIN (-425000000L)     /* -EMAX */
+#define MPD_MIN_ETINY (MPD_MIN_EMIN-(MPD_MAX_PREC-1))
+#define MPD_EXP_INF 1000000001L      /* allows for emax=999999999 in the tests */
+#define MPD_EXP_CLAMP (-2000000001L) /* allows for emin=-999999999 in the tests */
+#define MPD_MAXIMPORT 94444445L      /* ceil((2*MPD_MAX_PREC)/MPD_RDIGITS) */
+
+/* conversion specifiers */
+#define PRI_mpd_uint_t PRIu32
+#define PRI_mpd_ssize_t PRIi32
+
+#if MPD_SIZE_MAX != MPD_UINT_MAX
+  #error "unsupported platform: need mpd_size_t == mpd_uint_t"
+#endif
+
+
+/******************************************************************************/
+/*                                Context                                     */
+/******************************************************************************/
+
+enum {
+    MPD_ROUND_UP,          /* round away from 0               */
+    MPD_ROUND_DOWN,        /* round toward 0 (truncate)       */
+    MPD_ROUND_CEILING,     /* round toward +infinity          */
+    MPD_ROUND_FLOOR,       /* round toward -infinity          */
+    MPD_ROUND_HALF_UP,     /* 0.5 is rounded up               */
+    MPD_ROUND_HALF_DOWN,   /* 0.5 is rounded down             */
+    MPD_ROUND_HALF_EVEN,   /* 0.5 is rounded to even          */
+    MPD_ROUND_05UP,        /* round zero or five away from 0  */
+    MPD_ROUND_TRUNC,       /* truncate, but set infinity      */
+    MPD_ROUND_GUARD
+};
+
+enum { MPD_CLAMP_DEFAULT, MPD_CLAMP_IEEE_754, MPD_CLAMP_GUARD };
+
+IMPORTEXPORT extern const char *mpd_round_string[MPD_ROUND_GUARD];
+IMPORTEXPORT extern const char *mpd_clamp_string[MPD_CLAMP_GUARD];
+
+
+typedef struct mpd_context_t {
+    mpd_ssize_t prec;   /* precision */
+    mpd_ssize_t emax;   /* max positive exp */
+    mpd_ssize_t emin;   /* min negative exp */
+    uint32_t traps;     /* status events that should be trapped */
+    uint32_t status;    /* status flags */
+    uint32_t newtrap;   /* set by mpd_addstatus_raise() */
+    int      round;     /* rounding mode */
+    int      clamp;     /* clamp mode */
+    int      allcr;     /* all functions correctly rounded */
+} mpd_context_t;
+
+
+/* Status flags */
+#define MPD_Clamped             0x00000001U
+#define MPD_Conversion_syntax   0x00000002U
+#define MPD_Division_by_zero    0x00000004U
+#define MPD_Division_impossible 0x00000008U
+#define MPD_Division_undefined  0x00000010U
+#define MPD_Fpu_error           0x00000020U
+#define MPD_Inexact             0x00000040U
+#define MPD_Invalid_context     0x00000080U
+#define MPD_Invalid_operation   0x00000100U
+#define MPD_Malloc_error        0x00000200U
+#define MPD_Not_implemented     0x00000400U
+#define MPD_Overflow            0x00000800U
+#define MPD_Rounded             0x00001000U
+#define MPD_Subnormal           0x00002000U
+#define MPD_Underflow           0x00004000U
+#define MPD_Max_status         (0x00008000U-1U)
+
+/* Conditions that result in an IEEE 754 exception */
+#define MPD_IEEE_Invalid_operation (MPD_Conversion_syntax |   \
+                                    MPD_Division_impossible | \
+                                    MPD_Division_undefined |  \
+                                    MPD_Fpu_error |           \
+                                    MPD_Invalid_context |     \
+                                    MPD_Invalid_operation |   \
+                                    MPD_Malloc_error)         \
+
+/* Errors that require the result of an operation to be set to NaN */
+#define MPD_Errors (MPD_IEEE_Invalid_operation | \
+                    MPD_Division_by_zero)
+
+/* Default traps */
+#define MPD_Traps (MPD_IEEE_Invalid_operation | \
+                   MPD_Division_by_zero |       \
+                   MPD_Overflow |               \
+                   MPD_Underflow)
+
+/* Official name */
+#define MPD_Insufficient_storage MPD_Malloc_error
+
+/* IEEE 754 interchange format contexts */
+#define MPD_IEEE_CONTEXT_MAX_BITS 512 /* 16*(log2(MPD_MAX_EMAX / 3)-3) */
+#define MPD_DECIMAL32 32
+#define MPD_DECIMAL64 64
+#define MPD_DECIMAL128 128
+
+
+#define MPD_MINALLOC_MIN 2
+#define MPD_MINALLOC_MAX 64
+IMPORTEXPORT extern mpd_ssize_t MPD_MINALLOC;
+IMPORTEXPORT extern void (* mpd_traphandler)(mpd_context_t *);
+IMPORTEXPORT void mpd_dflt_traphandler(mpd_context_t *);
+
+IMPORTEXPORT void mpd_setminalloc(mpd_ssize_t n);
+IMPORTEXPORT void mpd_init(mpd_context_t *ctx, mpd_ssize_t prec);
+
+IMPORTEXPORT void mpd_maxcontext(mpd_context_t *ctx);
+IMPORTEXPORT void mpd_defaultcontext(mpd_context_t *ctx);
+IMPORTEXPORT void mpd_basiccontext(mpd_context_t *ctx);
+IMPORTEXPORT int mpd_ieee_context(mpd_context_t *ctx, int bits);
+
+IMPORTEXPORT mpd_ssize_t mpd_getprec(const mpd_context_t *ctx);
+IMPORTEXPORT mpd_ssize_t mpd_getemax(const mpd_context_t *ctx);
+IMPORTEXPORT mpd_ssize_t mpd_getemin(const mpd_context_t *ctx);
+IMPORTEXPORT int mpd_getround(const mpd_context_t *ctx);
+IMPORTEXPORT uint32_t mpd_gettraps(const mpd_context_t *ctx);
+IMPORTEXPORT uint32_t mpd_getstatus(const mpd_context_t *ctx);
+IMPORTEXPORT int mpd_getclamp(const mpd_context_t *ctx);
+IMPORTEXPORT int mpd_getcr(const mpd_context_t *ctx);
+
+IMPORTEXPORT int mpd_qsetprec(mpd_context_t *ctx, mpd_ssize_t prec);
+IMPORTEXPORT int mpd_qsetemax(mpd_context_t *ctx, mpd_ssize_t emax);
+IMPORTEXPORT int mpd_qsetemin(mpd_context_t *ctx, mpd_ssize_t emin);
+IMPORTEXPORT int mpd_qsetround(mpd_context_t *ctx, int newround);
+IMPORTEXPORT int mpd_qsettraps(mpd_context_t *ctx, uint32_t flags);
+IMPORTEXPORT int mpd_qsetstatus(mpd_context_t *ctx, uint32_t flags);
+IMPORTEXPORT int mpd_qsetclamp(mpd_context_t *ctx, int c);
+IMPORTEXPORT int mpd_qsetcr(mpd_context_t *ctx, int c);
+IMPORTEXPORT void mpd_addstatus_raise(mpd_context_t *ctx, uint32_t flags);
+
+
+/******************************************************************************/
+/*                           Decimal Arithmetic                               */
+/******************************************************************************/
+
+/* mpd_t flags */
+#define MPD_POS                 ((uint8_t)0)
+#define MPD_NEG                 ((uint8_t)1)
+#define MPD_INF                 ((uint8_t)2)
+#define MPD_NAN                 ((uint8_t)4)
+#define MPD_SNAN                ((uint8_t)8)
+#define MPD_SPECIAL (MPD_INF|MPD_NAN|MPD_SNAN)
+#define MPD_STATIC              ((uint8_t)16)
+#define MPD_STATIC_DATA         ((uint8_t)32)
+#define MPD_SHARED_DATA         ((uint8_t)64)
+#define MPD_CONST_DATA          ((uint8_t)128)
+#define MPD_DATAFLAGS (MPD_STATIC_DATA|MPD_SHARED_DATA|MPD_CONST_DATA)
+
+/* mpd_t */
+typedef struct mpd_t {
+    uint8_t flags;
+    mpd_ssize_t exp;
+    mpd_ssize_t digits;
+    mpd_ssize_t len;
+    mpd_ssize_t alloc;
+    mpd_uint_t *data;
+} mpd_t;
+
+
+typedef unsigned char uchar;
+
+
+/******************************************************************************/
+/*                       Quiet, thread-safe functions                         */
+/******************************************************************************/
+
+/* format specification */
+typedef struct mpd_spec_t {
+    mpd_ssize_t min_width; /* minimum field width */
+    mpd_ssize_t prec;      /* fraction digits or significant digits */
+    char type;             /* conversion specifier */
+    char align;            /* alignment */
+    char sign;             /* sign printing/alignment */
+    char fill[5];          /* fill character */
+    const char *dot;       /* decimal point */
+    const char *sep;       /* thousands separator */
+    const char *grouping;  /* grouping of digits */
+} mpd_spec_t;
+
+/* output to a string */
+IMPORTEXPORT char *mpd_to_sci(const mpd_t *dec, int fmt);
+IMPORTEXPORT char *mpd_to_eng(const mpd_t *dec, int fmt);
+IMPORTEXPORT mpd_ssize_t mpd_to_sci_size(char **res, const mpd_t *dec, int fmt);
+IMPORTEXPORT mpd_ssize_t mpd_to_eng_size(char **res, const mpd_t *dec, int fmt);
+IMPORTEXPORT int mpd_validate_lconv(mpd_spec_t *spec);
+IMPORTEXPORT int mpd_parse_fmt_str(mpd_spec_t *spec, const char *fmt, int caps);
+IMPORTEXPORT char * mpd_qformat_spec(const mpd_t *dec, const mpd_spec_t *spec, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT char *mpd_qformat(const mpd_t *dec, const char *fmt, const mpd_context_t *ctx, uint32_t *status);
+
+#define MPD_NUM_FLAGS 15
+#define MPD_MAX_FLAG_STRING 208
+#define MPD_MAX_FLAG_LIST (MPD_MAX_FLAG_STRING+18)
+#define MPD_MAX_SIGNAL_LIST 121
+IMPORTEXPORT int mpd_snprint_flags(char *dest, int nmemb, uint32_t flags);
+IMPORTEXPORT int mpd_lsnprint_flags(char *dest, int nmemb, uint32_t flags, const char *flag_string[]);
+IMPORTEXPORT int mpd_lsnprint_signals(char *dest, int nmemb, uint32_t flags, const char *signal_string[]);
+
+/* output to a file */
+IMPORTEXPORT void mpd_fprint(FILE *file, const mpd_t *dec);
+IMPORTEXPORT void mpd_print(const mpd_t *dec);
+
+/* assignment from a string */
+IMPORTEXPORT void mpd_qset_string(mpd_t *dec, const char *s, const mpd_context_t *ctx, uint32_t *status);
+
+/* set to NaN with error flags */
+IMPORTEXPORT void mpd_seterror(mpd_t *result, uint32_t flags, uint32_t *status);
+/* set a special with sign and type */
+IMPORTEXPORT void mpd_setspecial(mpd_t *dec, uint8_t sign, uint8_t type);
+/* set coefficient to zero or all nines */
+IMPORTEXPORT void mpd_zerocoeff(mpd_t *result);
+IMPORTEXPORT void mpd_qmaxcoeff(mpd_t *result, const mpd_context_t *ctx, uint32_t *status);
+
+/* quietly assign a C integer type to an mpd_t */
+IMPORTEXPORT void mpd_qset_ssize(mpd_t *result, mpd_ssize_t a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qset_i32(mpd_t *result, int32_t a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qset_uint(mpd_t *result, mpd_uint_t a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qset_u32(mpd_t *result, uint32_t a, const mpd_context_t *ctx, uint32_t *status);
+#ifndef LEGACY_COMPILER
+IMPORTEXPORT void mpd_qset_i64(mpd_t *result, int64_t a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qset_u64(mpd_t *result, uint64_t a, const mpd_context_t *ctx, uint32_t *status);
+#endif
+
+/* quietly assign a C integer type to an mpd_t with a static coefficient */
+IMPORTEXPORT void mpd_qsset_ssize(mpd_t *result, mpd_ssize_t a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qsset_i32(mpd_t *result, int32_t a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qsset_uint(mpd_t *result, mpd_uint_t a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qsset_u32(mpd_t *result, uint32_t a, const mpd_context_t *ctx, uint32_t *status);
+
+/* quietly get a C integer type from an mpd_t */
+IMPORTEXPORT mpd_ssize_t mpd_qget_ssize(const mpd_t *dec, uint32_t *status);
+IMPORTEXPORT mpd_uint_t mpd_qget_uint(const mpd_t *dec, uint32_t *status);
+IMPORTEXPORT mpd_uint_t mpd_qabs_uint(const mpd_t *dec, uint32_t *status);
+
+IMPORTEXPORT int32_t mpd_qget_i32(const mpd_t *dec, uint32_t *status);
+IMPORTEXPORT uint32_t mpd_qget_u32(const mpd_t *dec, uint32_t *status);
+#ifndef LEGACY_COMPILER
+IMPORTEXPORT int64_t mpd_qget_i64(const mpd_t *dec, uint32_t *status);
+IMPORTEXPORT uint64_t mpd_qget_u64(const mpd_t *dec, uint32_t *status);
+#endif
+
+/* quiet functions */
+IMPORTEXPORT int mpd_qcheck_nan(mpd_t *nanresult, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT int mpd_qcheck_nans(mpd_t *nanresult, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qfinalize(mpd_t *result, const mpd_context_t *ctx, uint32_t *status);
+
+IMPORTEXPORT const char * mpd_class(const mpd_t *a, const mpd_context_t *ctx);
+
+IMPORTEXPORT int mpd_qcopy(mpd_t *result, const mpd_t *a,  uint32_t *status);
+IMPORTEXPORT mpd_t *mpd_qncopy(const mpd_t *a);
+IMPORTEXPORT int mpd_qcopy_abs(mpd_t *result, const mpd_t *a, uint32_t *status);
+IMPORTEXPORT int mpd_qcopy_negate(mpd_t *result, const mpd_t *a, uint32_t *status);
+IMPORTEXPORT int mpd_qcopy_sign(mpd_t *result, const mpd_t *a, const mpd_t *b, uint32_t *status);
+
+IMPORTEXPORT void mpd_qand(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qinvert(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qlogb(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qor(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qscaleb(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qxor(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT int mpd_same_quantum(const mpd_t *a, const mpd_t *b);
+
+IMPORTEXPORT void mpd_qrotate(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT int mpd_qshiftl(mpd_t *result, const mpd_t *a, mpd_ssize_t n, uint32_t *status);
+IMPORTEXPORT mpd_uint_t mpd_qshiftr(mpd_t *result, const mpd_t *a, mpd_ssize_t n, uint32_t *status);
+IMPORTEXPORT mpd_uint_t mpd_qshiftr_inplace(mpd_t *result, mpd_ssize_t n);
+IMPORTEXPORT void mpd_qshift(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qshiftn(mpd_t *result, const mpd_t *a, mpd_ssize_t n, const mpd_context_t *ctx, uint32_t *status);
+
+IMPORTEXPORT int mpd_qcmp(const mpd_t *a, const mpd_t *b, uint32_t *status);
+IMPORTEXPORT int mpd_qcompare(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT int mpd_qcompare_signal(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT int mpd_cmp_total(const mpd_t *a, const mpd_t *b);
+IMPORTEXPORT int mpd_cmp_total_mag(const mpd_t *a, const mpd_t *b);
+IMPORTEXPORT int mpd_compare_total(mpd_t *result, const mpd_t *a, const mpd_t *b);
+IMPORTEXPORT int mpd_compare_total_mag(mpd_t *result, const mpd_t *a, const mpd_t *b);
+
+IMPORTEXPORT void mpd_qround_to_intx(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qround_to_int(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qtrunc(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qfloor(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qceil(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+
+IMPORTEXPORT void mpd_qabs(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qmax(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qmax_mag(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qmin(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qmin_mag(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qminus(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qplus(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qnext_minus(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qnext_plus(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qnext_toward(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qquantize(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qrescale(mpd_t *result, const mpd_t *a, mpd_ssize_t exp, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qrescale_fmt(mpd_t *result, const mpd_t *a, mpd_ssize_t exp, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qreduce(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qadd(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qadd_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qadd_i32(mpd_t *result, const mpd_t *a, int32_t b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qadd_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qadd_u32(mpd_t *result, const mpd_t *a, uint32_t b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qsub(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qsub_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qsub_i32(mpd_t *result, const mpd_t *a, int32_t b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qsub_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qsub_u32(mpd_t *result, const mpd_t *a, uint32_t b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qmul(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qmul_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qmul_i32(mpd_t *result, const mpd_t *a, int32_t b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qmul_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qmul_u32(mpd_t *result, const mpd_t *a, uint32_t b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qfma(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_t *c, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qdiv(mpd_t *q, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qdiv_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qdiv_i32(mpd_t *result, const mpd_t *a, int32_t b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qdiv_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qdiv_u32(mpd_t *result, const mpd_t *a, uint32_t b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qdivint(mpd_t *q, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qrem(mpd_t *r, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qrem_near(mpd_t *r, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qdivmod(mpd_t *q, mpd_t *r, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qpow(mpd_t *result, const mpd_t *base, const mpd_t *exp, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qpowmod(mpd_t *result, const mpd_t *base, const mpd_t *exp, const mpd_t *mod, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qexp(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qln10(mpd_t *result, mpd_ssize_t prec, uint32_t *status);
+IMPORTEXPORT void mpd_qln(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qlog10(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qsqrt(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qinvroot(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+
+#ifndef LEGACY_COMPILER
+IMPORTEXPORT void mpd_qadd_i64(mpd_t *result, const mpd_t *a, int64_t b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qadd_u64(mpd_t *result, const mpd_t *a, uint64_t b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qsub_i64(mpd_t *result, const mpd_t *a, int64_t b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qsub_u64(mpd_t *result, const mpd_t *a, uint64_t b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qmul_i64(mpd_t *result, const mpd_t *a, int64_t b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qmul_u64(mpd_t *result, const mpd_t *a, uint64_t b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qdiv_i64(mpd_t *result, const mpd_t *a, int64_t b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qdiv_u64(mpd_t *result, const mpd_t *a, uint64_t b, const mpd_context_t *ctx, uint32_t *status);
+#endif
+
+
+IMPORTEXPORT size_t mpd_sizeinbase(const mpd_t *a, uint32_t base);
+IMPORTEXPORT void mpd_qimport_u16(mpd_t *result, const uint16_t *srcdata, size_t srclen,
+                                  uint8_t srcsign, uint32_t srcbase,
+                                  const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qimport_u32(mpd_t *result, const uint32_t *srcdata, size_t srclen,
+                                  uint8_t srcsign, uint32_t srcbase,
+                                  const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT size_t mpd_qexport_u16(uint16_t **rdata, size_t rlen, uint32_t base,
+                                    const mpd_t *src, uint32_t *status);
+IMPORTEXPORT size_t mpd_qexport_u32(uint32_t **rdata, size_t rlen, uint32_t base,
+                                    const mpd_t *src, uint32_t *status);
+
+
+/******************************************************************************/
+/*                           Signalling functions                             */
+/******************************************************************************/
+
+IMPORTEXPORT char * mpd_format(const mpd_t *dec, const char *fmt, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_import_u16(mpd_t *result, const uint16_t *srcdata, size_t srclen, uint8_t srcsign, uint32_t base, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_import_u32(mpd_t *result, const uint32_t *srcdata, size_t srclen, uint8_t srcsign, uint32_t base, mpd_context_t *ctx);
+IMPORTEXPORT size_t mpd_export_u16(uint16_t **rdata, size_t rlen, uint32_t base, const mpd_t *src, mpd_context_t *ctx);
+IMPORTEXPORT size_t mpd_export_u32(uint32_t **rdata, size_t rlen, uint32_t base, const mpd_t *src, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_finalize(mpd_t *result, mpd_context_t *ctx);
+IMPORTEXPORT int mpd_check_nan(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT int mpd_check_nans(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_set_string(mpd_t *result, const char *s, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_maxcoeff(mpd_t *result, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_sset_ssize(mpd_t *result, mpd_ssize_t a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_sset_i32(mpd_t *result, int32_t a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_sset_uint(mpd_t *result, mpd_uint_t a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_sset_u32(mpd_t *result, uint32_t a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_set_ssize(mpd_t *result, mpd_ssize_t a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_set_i32(mpd_t *result, int32_t a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_set_uint(mpd_t *result, mpd_uint_t a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_set_u32(mpd_t *result, uint32_t a, mpd_context_t *ctx);
+#ifndef LEGACY_COMPILER
+IMPORTEXPORT void mpd_set_i64(mpd_t *result, int64_t a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_set_u64(mpd_t *result, uint64_t a, mpd_context_t *ctx);
+#endif
+IMPORTEXPORT mpd_ssize_t mpd_get_ssize(const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT mpd_uint_t mpd_get_uint(const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT mpd_uint_t mpd_abs_uint(const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT int32_t mpd_get_i32(const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT uint32_t mpd_get_u32(const mpd_t *a, mpd_context_t *ctx);
+#ifndef LEGACY_COMPILER
+IMPORTEXPORT int64_t mpd_get_i64(const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT uint64_t mpd_get_u64(const mpd_t *a, mpd_context_t *ctx);
+#endif
+IMPORTEXPORT void mpd_and(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_copy(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_canonical(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_copy_abs(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_copy_negate(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_copy_sign(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_invert(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_logb(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_or(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_rotate(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_scaleb(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_shiftl(mpd_t *result, const mpd_t *a, mpd_ssize_t n, mpd_context_t *ctx);
+IMPORTEXPORT mpd_uint_t mpd_shiftr(mpd_t *result, const mpd_t *a, mpd_ssize_t n, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_shiftn(mpd_t *result, const mpd_t *a, mpd_ssize_t n, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_shift(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_xor(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_abs(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT int mpd_cmp(const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT int mpd_compare(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT int mpd_compare_signal(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_add(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_add_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_add_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_add_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_add_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_sub(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_sub_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_sub_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_sub_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_sub_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_div(mpd_t *q, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_div_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_div_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_div_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_div_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_divmod(mpd_t *q, mpd_t *r, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_divint(mpd_t *q, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_exp(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_fma(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_t *c, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_ln(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_log10(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_max(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_max_mag(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_min(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_min_mag(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_minus(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_mul(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_mul_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_mul_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_mul_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_mul_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_next_minus(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_next_plus(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_next_toward(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_plus(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_pow(mpd_t *result, const mpd_t *base, const mpd_t *exp, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_powmod(mpd_t *result, const mpd_t *base, const mpd_t *exp, const mpd_t *mod, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_quantize(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_rescale(mpd_t *result, const mpd_t *a, mpd_ssize_t exp, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_reduce(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_rem(mpd_t *r, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_rem_near(mpd_t *r, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_round_to_intx(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_round_to_int(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_trunc(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_floor(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_ceil(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_sqrt(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_invroot(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+
+#ifndef LEGACY_COMPILER
+IMPORTEXPORT void mpd_add_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_add_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_sub_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_sub_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_div_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_div_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_mul_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_mul_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx);
+#endif
+
+
+/******************************************************************************/
+/*                       Get attributes of a decimal                          */
+/******************************************************************************/
+
+IMPORTEXPORT EXTINLINE mpd_ssize_t mpd_adjexp(const mpd_t *dec);
+IMPORTEXPORT EXTINLINE mpd_ssize_t mpd_etiny(const mpd_context_t *ctx);
+IMPORTEXPORT EXTINLINE mpd_ssize_t mpd_etop(const mpd_context_t *ctx);
+IMPORTEXPORT EXTINLINE mpd_uint_t mpd_msword(const mpd_t *dec);
+IMPORTEXPORT EXTINLINE int mpd_word_digits(mpd_uint_t word);
+/* most significant digit of a word */
+IMPORTEXPORT EXTINLINE mpd_uint_t mpd_msd(mpd_uint_t word);
+/* least significant digit of a word */
+IMPORTEXPORT EXTINLINE mpd_uint_t mpd_lsd(mpd_uint_t word);
+/* coefficient size needed to store 'digits' */
+IMPORTEXPORT EXTINLINE mpd_ssize_t mpd_digits_to_size(mpd_ssize_t digits);
+/* number of digits in the exponent, undefined for MPD_SSIZE_MIN */
+IMPORTEXPORT EXTINLINE int mpd_exp_digits(mpd_ssize_t exp);
+IMPORTEXPORT EXTINLINE int mpd_iscanonical(const mpd_t *dec UNUSED);
+IMPORTEXPORT EXTINLINE int mpd_isfinite(const mpd_t *dec);
+IMPORTEXPORT EXTINLINE int mpd_isinfinite(const mpd_t *dec);
+IMPORTEXPORT EXTINLINE int mpd_isinteger(const mpd_t *dec);
+IMPORTEXPORT EXTINLINE int mpd_isnan(const mpd_t *dec);
+IMPORTEXPORT EXTINLINE int mpd_isnegative(const mpd_t *dec);
+IMPORTEXPORT EXTINLINE int mpd_ispositive(const mpd_t *dec);
+IMPORTEXPORT EXTINLINE int mpd_isqnan(const mpd_t *dec);
+IMPORTEXPORT EXTINLINE int mpd_issigned(const mpd_t *dec);
+IMPORTEXPORT EXTINLINE int mpd_issnan(const mpd_t *dec);
+IMPORTEXPORT EXTINLINE int mpd_isspecial(const mpd_t *dec);
+IMPORTEXPORT EXTINLINE int mpd_iszero(const mpd_t *dec);
+/* undefined for special numbers */
+IMPORTEXPORT EXTINLINE int mpd_iszerocoeff(const mpd_t *dec);
+IMPORTEXPORT EXTINLINE int mpd_isnormal(const mpd_t *dec, const mpd_context_t *ctx);
+IMPORTEXPORT EXTINLINE int mpd_issubnormal(const mpd_t *dec, const mpd_context_t *ctx);
+/* odd word */
+IMPORTEXPORT EXTINLINE int mpd_isoddword(mpd_uint_t word);
+/* odd coefficient */
+IMPORTEXPORT EXTINLINE int mpd_isoddcoeff(const mpd_t *dec);
+/* odd decimal, only defined for integers */
+IMPORTEXPORT int mpd_isodd(const mpd_t *dec);
+/* even decimal, only defined for integers */
+IMPORTEXPORT int mpd_iseven(const mpd_t *dec);
+/* 0 if dec is positive, 1 if dec is negative */
+IMPORTEXPORT EXTINLINE uint8_t mpd_sign(const mpd_t *dec);
+/* 1 if dec is positive, -1 if dec is negative */
+IMPORTEXPORT EXTINLINE int mpd_arith_sign(const mpd_t *dec);
+IMPORTEXPORT EXTINLINE long mpd_radix(void);
+IMPORTEXPORT EXTINLINE int mpd_isdynamic(const mpd_t *dec);
+IMPORTEXPORT EXTINLINE int mpd_isstatic(const mpd_t *dec);
+IMPORTEXPORT EXTINLINE int mpd_isdynamic_data(const mpd_t *dec);
+IMPORTEXPORT EXTINLINE int mpd_isstatic_data(const mpd_t *dec);
+IMPORTEXPORT EXTINLINE int mpd_isshared_data(const mpd_t *dec);
+IMPORTEXPORT EXTINLINE int mpd_isconst_data(const mpd_t *dec);
+IMPORTEXPORT mpd_ssize_t mpd_trail_zeros(const mpd_t *dec);
+
+
+/******************************************************************************/
+/*                       Set attributes of a decimal                          */
+/******************************************************************************/
+
+/* set number of decimal digits in the coefficient */
+IMPORTEXPORT EXTINLINE void mpd_setdigits(mpd_t *result);
+IMPORTEXPORT EXTINLINE void mpd_set_sign(mpd_t *result, uint8_t sign);
+/* copy sign from another decimal */
+IMPORTEXPORT EXTINLINE void mpd_signcpy(mpd_t *result, const mpd_t *a);
+IMPORTEXPORT EXTINLINE void mpd_set_infinity(mpd_t *result);
+IMPORTEXPORT EXTINLINE void mpd_set_qnan(mpd_t *result);
+IMPORTEXPORT EXTINLINE void mpd_set_snan(mpd_t *result);
+IMPORTEXPORT EXTINLINE void mpd_set_negative(mpd_t *result);
+IMPORTEXPORT EXTINLINE void mpd_set_positive(mpd_t *result);
+IMPORTEXPORT EXTINLINE void mpd_set_dynamic(mpd_t *result);
+IMPORTEXPORT EXTINLINE void mpd_set_static(mpd_t *result);
+IMPORTEXPORT EXTINLINE void mpd_set_dynamic_data(mpd_t *result);
+IMPORTEXPORT EXTINLINE void mpd_set_static_data(mpd_t *result);
+IMPORTEXPORT EXTINLINE void mpd_set_shared_data(mpd_t *result);
+IMPORTEXPORT EXTINLINE void mpd_set_const_data(mpd_t *result);
+IMPORTEXPORT EXTINLINE void mpd_clear_flags(mpd_t *result);
+IMPORTEXPORT EXTINLINE void mpd_set_flags(mpd_t *result, uint8_t flags);
+IMPORTEXPORT EXTINLINE void mpd_copy_flags(mpd_t *result, const mpd_t *a);
+
+
+/******************************************************************************/
+/*                              Error Macros                                  */
+/******************************************************************************/
+
+#define mpd_err_fatal(...) \
+    do {fprintf(stderr, "%s:%d: error: ", __FILE__, __LINE__); \
+        fprintf(stderr, __VA_ARGS__);  fputc('\n', stderr);    \
+        abort();                                               \
+    } while (0)
+#define mpd_err_warn(...) \
+    do {fprintf(stderr, "%s:%d: warning: ", __FILE__, __LINE__); \
+        fprintf(stderr, __VA_ARGS__); fputc('\n', stderr);       \
+    } while (0)
+
+
+/******************************************************************************/
+/*                            Memory handling                                 */
+/******************************************************************************/
+
+IMPORTEXPORT extern void *(* mpd_mallocfunc)(size_t size);
+IMPORTEXPORT extern void *(* mpd_callocfunc)(size_t nmemb, size_t size);
+IMPORTEXPORT extern void *(* mpd_reallocfunc)(void *ptr, size_t size);
+IMPORTEXPORT extern void (* mpd_free)(void *ptr);
+
+IMPORTEXPORT void *mpd_callocfunc_em(size_t nmemb, size_t size);
+
+IMPORTEXPORT void *mpd_alloc(mpd_size_t nmemb, mpd_size_t size);
+IMPORTEXPORT void *mpd_calloc(mpd_size_t nmemb, mpd_size_t size);
+IMPORTEXPORT void *mpd_realloc(void *ptr, mpd_size_t nmemb, mpd_size_t size, uint8_t *err);
+IMPORTEXPORT void *mpd_sh_alloc(mpd_size_t struct_size, mpd_size_t nmemb, mpd_size_t size);
+
+IMPORTEXPORT mpd_t *mpd_qnew(void);
+IMPORTEXPORT mpd_t *mpd_new(mpd_context_t *ctx);
+IMPORTEXPORT mpd_t *mpd_qnew_size(mpd_ssize_t size);
+IMPORTEXPORT void mpd_del(mpd_t *dec);
+
+IMPORTEXPORT void mpd_uint_zero(mpd_uint_t *dest, mpd_size_t len);
+IMPORTEXPORT int mpd_qresize(mpd_t *result, mpd_ssize_t size, uint32_t *status);
+IMPORTEXPORT int mpd_qresize_zero(mpd_t *result, mpd_ssize_t size, uint32_t *status);
+IMPORTEXPORT void mpd_minalloc(mpd_t *result);
+
+IMPORTEXPORT int mpd_resize(mpd_t *result, mpd_ssize_t size, mpd_context_t *ctx);
+IMPORTEXPORT int mpd_resize_zero(mpd_t *result, mpd_ssize_t size, mpd_context_t *ctx);
+
+
+#ifdef __cplusplus
+} /* END extern "C" */
+#endif
+
+
+#endif /* MPDECIMAL_H */
+
+
+

+ 737 - 0
mpdecimal/mpdecimal64vc.h

@@ -0,0 +1,737 @@
+/*
+ * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#ifndef MPDECIMAL_H
+#define MPDECIMAL_H
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <assert.h>
+
+#include "vccompat.h"
+#ifndef UNUSED
+  #define UNUSED
+#endif
+#define MPD_PRAGMA(x)
+#define MPD_HIDE_SYMBOLS_START
+#define MPD_HIDE_SYMBOLS_END
+#define EXTINLINE extern inline
+
+#define IMPORTEXPORT
+
+#if defined (BUILD_DLL)
+  #undef IMPORTEXPORT
+  #define IMPORTEXPORT __declspec( dllexport )
+#elif defined (USE_DLL)
+  #undef IMPORTEXPORT
+  #define IMPORTEXPORT __declspec( dllimport )
+#endif
+
+
+#if !defined(LEGACY_COMPILER)
+  #if !defined(UINT64_MAX)
+    /* The following #error is just a warning. If the compiler indeed does
+     * not have uint64_t, it is perfectly safe to comment out the #error. */
+    #error "Warning: Compiler without uint64_t. Comment out this line."
+    #define LEGACY_COMPILER
+  #endif
+#endif
+
+
+/******************************************************************************/
+/*                                  Version                                   */
+/******************************************************************************/
+
+#define MPD_MAJOR_VERSION 2
+#define MPD_MINOR_VERSION 4
+#define MPD_MICRO_VERSION 1
+
+#define MPD_VERSION "2.4.1"
+
+#define MPD_VERSION_HEX ((MPD_MAJOR_VERSION << 24) | \
+                         (MPD_MINOR_VERSION << 16) | \
+                         (MPD_MICRO_VERSION <<  8))
+
+IMPORTEXPORT const char *mpd_version(void);
+
+
+/******************************************************************************/
+/*                      Types for 64 bit architectures                        */
+/******************************************************************************/
+
+/* types for modular and base arithmetic */
+#define MPD_UINT_MAX UINT64_MAX
+#define MPD_BITS_PER_UINT 64
+typedef uint64_t mpd_uint_t;  /* unsigned mod type */
+
+#define MPD_SIZE_MAX SIZE_MAX
+typedef size_t mpd_size_t; /* unsigned size type */
+
+/* type for exp, digits, len, prec */
+#define MPD_SSIZE_MAX INT64_MAX
+#define MPD_SSIZE_MIN INT64_MIN
+typedef int64_t mpd_ssize_t;
+#define _mpd_strtossize strtoll
+
+/* decimal arithmetic */
+#define MPD_RADIX 10000000000000000000ULL  /* 10**19 */
+#define MPD_RDIGITS 19
+#define MPD_MAX_POW10 19
+#define MPD_EXPDIGITS 19  /* MPD_EXPDIGITS <= MPD_RDIGITS+1 */
+
+#define MPD_MAXTRANSFORM_2N 4294967296ULL      /* 2**32 */
+#define MPD_MAX_PREC 999999999999999999LL
+#define MPD_MAX_PREC_LOG2 64
+#define MPD_ELIMIT  1000000000000000000LL
+#define MPD_MAX_EMAX   999999999999999999LL    /* ELIMIT-1 */
+#define MPD_MIN_EMIN  (-999999999999999999LL)  /* -EMAX */
+#define MPD_MIN_ETINY (MPD_MIN_EMIN-(MPD_MAX_PREC-1))
+#define MPD_EXP_INF 2000000000000000001LL
+#define MPD_EXP_CLAMP (-4000000000000000001LL)
+#define MPD_MAXIMPORT 105263157894736842L /* ceil((2*MPD_MAX_PREC)/MPD_RDIGITS) */
+
+/* conversion specifiers */
+#define PRI_mpd_uint_t PRIu64
+#define PRI_mpd_ssize_t PRIi64
+
+#if MPD_SIZE_MAX != MPD_UINT_MAX
+  #error "unsupported platform: need mpd_size_t == mpd_uint_t"
+#endif
+
+
+/******************************************************************************/
+/*                                Context                                     */
+/******************************************************************************/
+
+enum {
+    MPD_ROUND_UP,          /* round away from 0               */
+    MPD_ROUND_DOWN,        /* round toward 0 (truncate)       */
+    MPD_ROUND_CEILING,     /* round toward +infinity          */
+    MPD_ROUND_FLOOR,       /* round toward -infinity          */
+    MPD_ROUND_HALF_UP,     /* 0.5 is rounded up               */
+    MPD_ROUND_HALF_DOWN,   /* 0.5 is rounded down             */
+    MPD_ROUND_HALF_EVEN,   /* 0.5 is rounded to even          */
+    MPD_ROUND_05UP,        /* round zero or five away from 0  */
+    MPD_ROUND_TRUNC,       /* truncate, but set infinity      */
+    MPD_ROUND_GUARD
+};
+
+enum { MPD_CLAMP_DEFAULT, MPD_CLAMP_IEEE_754, MPD_CLAMP_GUARD };
+
+IMPORTEXPORT extern const char *mpd_round_string[MPD_ROUND_GUARD];
+IMPORTEXPORT extern const char *mpd_clamp_string[MPD_CLAMP_GUARD];
+
+
+typedef struct mpd_context_t {
+    mpd_ssize_t prec;   /* precision */
+    mpd_ssize_t emax;   /* max positive exp */
+    mpd_ssize_t emin;   /* min negative exp */
+    uint32_t traps;     /* status events that should be trapped */
+    uint32_t status;    /* status flags */
+    uint32_t newtrap;   /* set by mpd_addstatus_raise() */
+    int      round;     /* rounding mode */
+    int      clamp;     /* clamp mode */
+    int      allcr;     /* all functions correctly rounded */
+} mpd_context_t;
+
+
+/* Status flags */
+#define MPD_Clamped             0x00000001U
+#define MPD_Conversion_syntax   0x00000002U
+#define MPD_Division_by_zero    0x00000004U
+#define MPD_Division_impossible 0x00000008U
+#define MPD_Division_undefined  0x00000010U
+#define MPD_Fpu_error           0x00000020U
+#define MPD_Inexact             0x00000040U
+#define MPD_Invalid_context     0x00000080U
+#define MPD_Invalid_operation   0x00000100U
+#define MPD_Malloc_error        0x00000200U
+#define MPD_Not_implemented     0x00000400U
+#define MPD_Overflow            0x00000800U
+#define MPD_Rounded             0x00001000U
+#define MPD_Subnormal           0x00002000U
+#define MPD_Underflow           0x00004000U
+#define MPD_Max_status         (0x00008000U-1U)
+
+/* Conditions that result in an IEEE 754 exception */
+#define MPD_IEEE_Invalid_operation (MPD_Conversion_syntax |   \
+                                    MPD_Division_impossible | \
+                                    MPD_Division_undefined |  \
+                                    MPD_Fpu_error |           \
+                                    MPD_Invalid_context |     \
+                                    MPD_Invalid_operation |   \
+                                    MPD_Malloc_error)         \
+
+/* Errors that require the result of an operation to be set to NaN */
+#define MPD_Errors (MPD_IEEE_Invalid_operation | \
+                    MPD_Division_by_zero)
+
+/* Default traps */
+#define MPD_Traps (MPD_IEEE_Invalid_operation | \
+                   MPD_Division_by_zero |       \
+                   MPD_Overflow |               \
+                   MPD_Underflow)
+
+/* Official name */
+#define MPD_Insufficient_storage MPD_Malloc_error
+
+/* IEEE 754 interchange format contexts */
+#define MPD_IEEE_CONTEXT_MAX_BITS 512 /* 16*(log2(MPD_MAX_EMAX / 3)-3) */
+#define MPD_DECIMAL32 32
+#define MPD_DECIMAL64 64
+#define MPD_DECIMAL128 128
+
+
+#define MPD_MINALLOC_MIN 2
+#define MPD_MINALLOC_MAX 64
+IMPORTEXPORT extern mpd_ssize_t MPD_MINALLOC;
+IMPORTEXPORT extern void (* mpd_traphandler)(mpd_context_t *);
+IMPORTEXPORT void mpd_dflt_traphandler(mpd_context_t *);
+
+IMPORTEXPORT void mpd_setminalloc(mpd_ssize_t n);
+IMPORTEXPORT void mpd_init(mpd_context_t *ctx, mpd_ssize_t prec);
+
+IMPORTEXPORT void mpd_maxcontext(mpd_context_t *ctx);
+IMPORTEXPORT void mpd_defaultcontext(mpd_context_t *ctx);
+IMPORTEXPORT void mpd_basiccontext(mpd_context_t *ctx);
+IMPORTEXPORT int mpd_ieee_context(mpd_context_t *ctx, int bits);
+
+IMPORTEXPORT mpd_ssize_t mpd_getprec(const mpd_context_t *ctx);
+IMPORTEXPORT mpd_ssize_t mpd_getemax(const mpd_context_t *ctx);
+IMPORTEXPORT mpd_ssize_t mpd_getemin(const mpd_context_t *ctx);
+IMPORTEXPORT int mpd_getround(const mpd_context_t *ctx);
+IMPORTEXPORT uint32_t mpd_gettraps(const mpd_context_t *ctx);
+IMPORTEXPORT uint32_t mpd_getstatus(const mpd_context_t *ctx);
+IMPORTEXPORT int mpd_getclamp(const mpd_context_t *ctx);
+IMPORTEXPORT int mpd_getcr(const mpd_context_t *ctx);
+
+IMPORTEXPORT int mpd_qsetprec(mpd_context_t *ctx, mpd_ssize_t prec);
+IMPORTEXPORT int mpd_qsetemax(mpd_context_t *ctx, mpd_ssize_t emax);
+IMPORTEXPORT int mpd_qsetemin(mpd_context_t *ctx, mpd_ssize_t emin);
+IMPORTEXPORT int mpd_qsetround(mpd_context_t *ctx, int newround);
+IMPORTEXPORT int mpd_qsettraps(mpd_context_t *ctx, uint32_t flags);
+IMPORTEXPORT int mpd_qsetstatus(mpd_context_t *ctx, uint32_t flags);
+IMPORTEXPORT int mpd_qsetclamp(mpd_context_t *ctx, int c);
+IMPORTEXPORT int mpd_qsetcr(mpd_context_t *ctx, int c);
+IMPORTEXPORT void mpd_addstatus_raise(mpd_context_t *ctx, uint32_t flags);
+
+
+/******************************************************************************/
+/*                           Decimal Arithmetic                               */
+/******************************************************************************/
+
+/* mpd_t flags */
+#define MPD_POS                 ((uint8_t)0)
+#define MPD_NEG                 ((uint8_t)1)
+#define MPD_INF                 ((uint8_t)2)
+#define MPD_NAN                 ((uint8_t)4)
+#define MPD_SNAN                ((uint8_t)8)
+#define MPD_SPECIAL (MPD_INF|MPD_NAN|MPD_SNAN)
+#define MPD_STATIC              ((uint8_t)16)
+#define MPD_STATIC_DATA         ((uint8_t)32)
+#define MPD_SHARED_DATA         ((uint8_t)64)
+#define MPD_CONST_DATA          ((uint8_t)128)
+#define MPD_DATAFLAGS (MPD_STATIC_DATA|MPD_SHARED_DATA|MPD_CONST_DATA)
+
+/* mpd_t */
+typedef struct mpd_t {
+    uint8_t flags;
+    mpd_ssize_t exp;
+    mpd_ssize_t digits;
+    mpd_ssize_t len;
+    mpd_ssize_t alloc;
+    mpd_uint_t *data;
+} mpd_t;
+
+
+typedef unsigned char uchar;
+
+
+/******************************************************************************/
+/*                       Quiet, thread-safe functions                         */
+/******************************************************************************/
+
+/* format specification */
+typedef struct mpd_spec_t {
+    mpd_ssize_t min_width; /* minimum field width */
+    mpd_ssize_t prec;      /* fraction digits or significant digits */
+    char type;             /* conversion specifier */
+    char align;            /* alignment */
+    char sign;             /* sign printing/alignment */
+    char fill[5];          /* fill character */
+    const char *dot;       /* decimal point */
+    const char *sep;       /* thousands separator */
+    const char *grouping;  /* grouping of digits */
+} mpd_spec_t;
+
+/* output to a string */
+IMPORTEXPORT char *mpd_to_sci(const mpd_t *dec, int fmt);
+IMPORTEXPORT char *mpd_to_eng(const mpd_t *dec, int fmt);
+IMPORTEXPORT mpd_ssize_t mpd_to_sci_size(char **res, const mpd_t *dec, int fmt);
+IMPORTEXPORT mpd_ssize_t mpd_to_eng_size(char **res, const mpd_t *dec, int fmt);
+IMPORTEXPORT int mpd_validate_lconv(mpd_spec_t *spec);
+IMPORTEXPORT int mpd_parse_fmt_str(mpd_spec_t *spec, const char *fmt, int caps);
+IMPORTEXPORT char * mpd_qformat_spec(const mpd_t *dec, const mpd_spec_t *spec, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT char *mpd_qformat(const mpd_t *dec, const char *fmt, const mpd_context_t *ctx, uint32_t *status);
+
+#define MPD_NUM_FLAGS 15
+#define MPD_MAX_FLAG_STRING 208
+#define MPD_MAX_FLAG_LIST (MPD_MAX_FLAG_STRING+18)
+#define MPD_MAX_SIGNAL_LIST 121
+IMPORTEXPORT int mpd_snprint_flags(char *dest, int nmemb, uint32_t flags);
+IMPORTEXPORT int mpd_lsnprint_flags(char *dest, int nmemb, uint32_t flags, const char *flag_string[]);
+IMPORTEXPORT int mpd_lsnprint_signals(char *dest, int nmemb, uint32_t flags, const char *signal_string[]);
+
+/* output to a file */
+IMPORTEXPORT void mpd_fprint(FILE *file, const mpd_t *dec);
+IMPORTEXPORT void mpd_print(const mpd_t *dec);
+
+/* assignment from a string */
+IMPORTEXPORT void mpd_qset_string(mpd_t *dec, const char *s, const mpd_context_t *ctx, uint32_t *status);
+
+/* set to NaN with error flags */
+IMPORTEXPORT void mpd_seterror(mpd_t *result, uint32_t flags, uint32_t *status);
+/* set a special with sign and type */
+IMPORTEXPORT void mpd_setspecial(mpd_t *dec, uint8_t sign, uint8_t type);
+/* set coefficient to zero or all nines */
+IMPORTEXPORT void mpd_zerocoeff(mpd_t *result);
+IMPORTEXPORT void mpd_qmaxcoeff(mpd_t *result, const mpd_context_t *ctx, uint32_t *status);
+
+/* quietly assign a C integer type to an mpd_t */
+IMPORTEXPORT void mpd_qset_ssize(mpd_t *result, mpd_ssize_t a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qset_i32(mpd_t *result, int32_t a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qset_uint(mpd_t *result, mpd_uint_t a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qset_u32(mpd_t *result, uint32_t a, const mpd_context_t *ctx, uint32_t *status);
+#ifndef LEGACY_COMPILER
+IMPORTEXPORT void mpd_qset_i64(mpd_t *result, int64_t a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qset_u64(mpd_t *result, uint64_t a, const mpd_context_t *ctx, uint32_t *status);
+#endif
+
+/* quietly assign a C integer type to an mpd_t with a static coefficient */
+IMPORTEXPORT void mpd_qsset_ssize(mpd_t *result, mpd_ssize_t a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qsset_i32(mpd_t *result, int32_t a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qsset_uint(mpd_t *result, mpd_uint_t a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qsset_u32(mpd_t *result, uint32_t a, const mpd_context_t *ctx, uint32_t *status);
+
+/* quietly get a C integer type from an mpd_t */
+IMPORTEXPORT mpd_ssize_t mpd_qget_ssize(const mpd_t *dec, uint32_t *status);
+IMPORTEXPORT mpd_uint_t mpd_qget_uint(const mpd_t *dec, uint32_t *status);
+IMPORTEXPORT mpd_uint_t mpd_qabs_uint(const mpd_t *dec, uint32_t *status);
+
+IMPORTEXPORT int32_t mpd_qget_i32(const mpd_t *dec, uint32_t *status);
+IMPORTEXPORT uint32_t mpd_qget_u32(const mpd_t *dec, uint32_t *status);
+#ifndef LEGACY_COMPILER
+IMPORTEXPORT int64_t mpd_qget_i64(const mpd_t *dec, uint32_t *status);
+IMPORTEXPORT uint64_t mpd_qget_u64(const mpd_t *dec, uint32_t *status);
+#endif
+
+/* quiet functions */
+IMPORTEXPORT int mpd_qcheck_nan(mpd_t *nanresult, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT int mpd_qcheck_nans(mpd_t *nanresult, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qfinalize(mpd_t *result, const mpd_context_t *ctx, uint32_t *status);
+
+IMPORTEXPORT const char * mpd_class(const mpd_t *a, const mpd_context_t *ctx);
+
+IMPORTEXPORT int mpd_qcopy(mpd_t *result, const mpd_t *a,  uint32_t *status);
+IMPORTEXPORT mpd_t *mpd_qncopy(const mpd_t *a);
+IMPORTEXPORT int mpd_qcopy_abs(mpd_t *result, const mpd_t *a, uint32_t *status);
+IMPORTEXPORT int mpd_qcopy_negate(mpd_t *result, const mpd_t *a, uint32_t *status);
+IMPORTEXPORT int mpd_qcopy_sign(mpd_t *result, const mpd_t *a, const mpd_t *b, uint32_t *status);
+
+IMPORTEXPORT void mpd_qand(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qinvert(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qlogb(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qor(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qscaleb(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qxor(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT int mpd_same_quantum(const mpd_t *a, const mpd_t *b);
+
+IMPORTEXPORT void mpd_qrotate(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT int mpd_qshiftl(mpd_t *result, const mpd_t *a, mpd_ssize_t n, uint32_t *status);
+IMPORTEXPORT mpd_uint_t mpd_qshiftr(mpd_t *result, const mpd_t *a, mpd_ssize_t n, uint32_t *status);
+IMPORTEXPORT mpd_uint_t mpd_qshiftr_inplace(mpd_t *result, mpd_ssize_t n);
+IMPORTEXPORT void mpd_qshift(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qshiftn(mpd_t *result, const mpd_t *a, mpd_ssize_t n, const mpd_context_t *ctx, uint32_t *status);
+
+IMPORTEXPORT int mpd_qcmp(const mpd_t *a, const mpd_t *b, uint32_t *status);
+IMPORTEXPORT int mpd_qcompare(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT int mpd_qcompare_signal(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT int mpd_cmp_total(const mpd_t *a, const mpd_t *b);
+IMPORTEXPORT int mpd_cmp_total_mag(const mpd_t *a, const mpd_t *b);
+IMPORTEXPORT int mpd_compare_total(mpd_t *result, const mpd_t *a, const mpd_t *b);
+IMPORTEXPORT int mpd_compare_total_mag(mpd_t *result, const mpd_t *a, const mpd_t *b);
+
+IMPORTEXPORT void mpd_qround_to_intx(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qround_to_int(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qtrunc(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qfloor(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qceil(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+
+IMPORTEXPORT void mpd_qabs(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qmax(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qmax_mag(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qmin(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qmin_mag(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qminus(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qplus(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qnext_minus(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qnext_plus(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qnext_toward(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qquantize(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qrescale(mpd_t *result, const mpd_t *a, mpd_ssize_t exp, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qrescale_fmt(mpd_t *result, const mpd_t *a, mpd_ssize_t exp, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qreduce(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qadd(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qadd_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qadd_i32(mpd_t *result, const mpd_t *a, int32_t b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qadd_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qadd_u32(mpd_t *result, const mpd_t *a, uint32_t b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qsub(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qsub_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qsub_i32(mpd_t *result, const mpd_t *a, int32_t b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qsub_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qsub_u32(mpd_t *result, const mpd_t *a, uint32_t b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qmul(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qmul_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qmul_i32(mpd_t *result, const mpd_t *a, int32_t b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qmul_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qmul_u32(mpd_t *result, const mpd_t *a, uint32_t b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qfma(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_t *c, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qdiv(mpd_t *q, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qdiv_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qdiv_i32(mpd_t *result, const mpd_t *a, int32_t b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qdiv_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qdiv_u32(mpd_t *result, const mpd_t *a, uint32_t b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qdivint(mpd_t *q, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qrem(mpd_t *r, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qrem_near(mpd_t *r, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qdivmod(mpd_t *q, mpd_t *r, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qpow(mpd_t *result, const mpd_t *base, const mpd_t *exp, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qpowmod(mpd_t *result, const mpd_t *base, const mpd_t *exp, const mpd_t *mod, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qexp(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qln10(mpd_t *result, mpd_ssize_t prec, uint32_t *status);
+IMPORTEXPORT void mpd_qln(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qlog10(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qsqrt(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qinvroot(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+
+#ifndef LEGACY_COMPILER
+IMPORTEXPORT void mpd_qadd_i64(mpd_t *result, const mpd_t *a, int64_t b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qadd_u64(mpd_t *result, const mpd_t *a, uint64_t b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qsub_i64(mpd_t *result, const mpd_t *a, int64_t b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qsub_u64(mpd_t *result, const mpd_t *a, uint64_t b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qmul_i64(mpd_t *result, const mpd_t *a, int64_t b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qmul_u64(mpd_t *result, const mpd_t *a, uint64_t b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qdiv_i64(mpd_t *result, const mpd_t *a, int64_t b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qdiv_u64(mpd_t *result, const mpd_t *a, uint64_t b, const mpd_context_t *ctx, uint32_t *status);
+#endif
+
+
+IMPORTEXPORT size_t mpd_sizeinbase(const mpd_t *a, uint32_t base);
+IMPORTEXPORT void mpd_qimport_u16(mpd_t *result, const uint16_t *srcdata, size_t srclen,
+                                  uint8_t srcsign, uint32_t srcbase,
+                                  const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qimport_u32(mpd_t *result, const uint32_t *srcdata, size_t srclen,
+                                  uint8_t srcsign, uint32_t srcbase,
+                                  const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT size_t mpd_qexport_u16(uint16_t **rdata, size_t rlen, uint32_t base,
+                                    const mpd_t *src, uint32_t *status);
+IMPORTEXPORT size_t mpd_qexport_u32(uint32_t **rdata, size_t rlen, uint32_t base,
+                                    const mpd_t *src, uint32_t *status);
+
+
+/******************************************************************************/
+/*                           Signalling functions                             */
+/******************************************************************************/
+
+IMPORTEXPORT char * mpd_format(const mpd_t *dec, const char *fmt, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_import_u16(mpd_t *result, const uint16_t *srcdata, size_t srclen, uint8_t srcsign, uint32_t base, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_import_u32(mpd_t *result, const uint32_t *srcdata, size_t srclen, uint8_t srcsign, uint32_t base, mpd_context_t *ctx);
+IMPORTEXPORT size_t mpd_export_u16(uint16_t **rdata, size_t rlen, uint32_t base, const mpd_t *src, mpd_context_t *ctx);
+IMPORTEXPORT size_t mpd_export_u32(uint32_t **rdata, size_t rlen, uint32_t base, const mpd_t *src, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_finalize(mpd_t *result, mpd_context_t *ctx);
+IMPORTEXPORT int mpd_check_nan(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT int mpd_check_nans(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_set_string(mpd_t *result, const char *s, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_maxcoeff(mpd_t *result, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_sset_ssize(mpd_t *result, mpd_ssize_t a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_sset_i32(mpd_t *result, int32_t a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_sset_uint(mpd_t *result, mpd_uint_t a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_sset_u32(mpd_t *result, uint32_t a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_set_ssize(mpd_t *result, mpd_ssize_t a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_set_i32(mpd_t *result, int32_t a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_set_uint(mpd_t *result, mpd_uint_t a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_set_u32(mpd_t *result, uint32_t a, mpd_context_t *ctx);
+#ifndef LEGACY_COMPILER
+IMPORTEXPORT void mpd_set_i64(mpd_t *result, int64_t a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_set_u64(mpd_t *result, uint64_t a, mpd_context_t *ctx);
+#endif
+IMPORTEXPORT mpd_ssize_t mpd_get_ssize(const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT mpd_uint_t mpd_get_uint(const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT mpd_uint_t mpd_abs_uint(const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT int32_t mpd_get_i32(const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT uint32_t mpd_get_u32(const mpd_t *a, mpd_context_t *ctx);
+#ifndef LEGACY_COMPILER
+IMPORTEXPORT int64_t mpd_get_i64(const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT uint64_t mpd_get_u64(const mpd_t *a, mpd_context_t *ctx);
+#endif
+IMPORTEXPORT void mpd_and(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_copy(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_canonical(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_copy_abs(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_copy_negate(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_copy_sign(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_invert(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_logb(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_or(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_rotate(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_scaleb(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_shiftl(mpd_t *result, const mpd_t *a, mpd_ssize_t n, mpd_context_t *ctx);
+IMPORTEXPORT mpd_uint_t mpd_shiftr(mpd_t *result, const mpd_t *a, mpd_ssize_t n, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_shiftn(mpd_t *result, const mpd_t *a, mpd_ssize_t n, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_shift(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_xor(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_abs(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT int mpd_cmp(const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT int mpd_compare(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT int mpd_compare_signal(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_add(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_add_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_add_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_add_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_add_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_sub(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_sub_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_sub_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_sub_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_sub_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_div(mpd_t *q, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_div_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_div_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_div_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_div_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_divmod(mpd_t *q, mpd_t *r, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_divint(mpd_t *q, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_exp(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_fma(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_t *c, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_ln(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_log10(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_max(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_max_mag(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_min(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_min_mag(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_minus(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_mul(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_mul_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_mul_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_mul_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_mul_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_next_minus(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_next_plus(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_next_toward(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_plus(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_pow(mpd_t *result, const mpd_t *base, const mpd_t *exp, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_powmod(mpd_t *result, const mpd_t *base, const mpd_t *exp, const mpd_t *mod, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_quantize(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_rescale(mpd_t *result, const mpd_t *a, mpd_ssize_t exp, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_reduce(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_rem(mpd_t *r, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_rem_near(mpd_t *r, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_round_to_intx(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_round_to_int(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_trunc(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_floor(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_ceil(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_sqrt(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_invroot(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+
+#ifndef LEGACY_COMPILER
+IMPORTEXPORT void mpd_add_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_add_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_sub_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_sub_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_div_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_div_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_mul_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_mul_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx);
+#endif
+
+
+/******************************************************************************/
+/*                          Configuration specific                            */
+/******************************************************************************/
+
+IMPORTEXPORT void mpd_qsset_i64(mpd_t *result, int64_t a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_qsset_u64(mpd_t *result, uint64_t a, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_sset_i64(mpd_t *result, int64_t a, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_sset_u64(mpd_t *result, uint64_t a, mpd_context_t *ctx);
+
+
+
+/******************************************************************************/
+/*                       Get attributes of a decimal                          */
+/******************************************************************************/
+
+IMPORTEXPORT EXTINLINE mpd_ssize_t mpd_adjexp(const mpd_t *dec);
+IMPORTEXPORT EXTINLINE mpd_ssize_t mpd_etiny(const mpd_context_t *ctx);
+IMPORTEXPORT EXTINLINE mpd_ssize_t mpd_etop(const mpd_context_t *ctx);
+IMPORTEXPORT EXTINLINE mpd_uint_t mpd_msword(const mpd_t *dec);
+IMPORTEXPORT EXTINLINE int mpd_word_digits(mpd_uint_t word);
+/* most significant digit of a word */
+IMPORTEXPORT EXTINLINE mpd_uint_t mpd_msd(mpd_uint_t word);
+/* least significant digit of a word */
+IMPORTEXPORT EXTINLINE mpd_uint_t mpd_lsd(mpd_uint_t word);
+/* coefficient size needed to store 'digits' */
+IMPORTEXPORT EXTINLINE mpd_ssize_t mpd_digits_to_size(mpd_ssize_t digits);
+/* number of digits in the exponent, undefined for MPD_SSIZE_MIN */
+IMPORTEXPORT EXTINLINE int mpd_exp_digits(mpd_ssize_t exp);
+IMPORTEXPORT EXTINLINE int mpd_iscanonical(const mpd_t *dec UNUSED);
+IMPORTEXPORT EXTINLINE int mpd_isfinite(const mpd_t *dec);
+IMPORTEXPORT EXTINLINE int mpd_isinfinite(const mpd_t *dec);
+IMPORTEXPORT EXTINLINE int mpd_isinteger(const mpd_t *dec);
+IMPORTEXPORT EXTINLINE int mpd_isnan(const mpd_t *dec);
+IMPORTEXPORT EXTINLINE int mpd_isnegative(const mpd_t *dec);
+IMPORTEXPORT EXTINLINE int mpd_ispositive(const mpd_t *dec);
+IMPORTEXPORT EXTINLINE int mpd_isqnan(const mpd_t *dec);
+IMPORTEXPORT EXTINLINE int mpd_issigned(const mpd_t *dec);
+IMPORTEXPORT EXTINLINE int mpd_issnan(const mpd_t *dec);
+IMPORTEXPORT EXTINLINE int mpd_isspecial(const mpd_t *dec);
+IMPORTEXPORT EXTINLINE int mpd_iszero(const mpd_t *dec);
+/* undefined for special numbers */
+IMPORTEXPORT EXTINLINE int mpd_iszerocoeff(const mpd_t *dec);
+IMPORTEXPORT EXTINLINE int mpd_isnormal(const mpd_t *dec, const mpd_context_t *ctx);
+IMPORTEXPORT EXTINLINE int mpd_issubnormal(const mpd_t *dec, const mpd_context_t *ctx);
+/* odd word */
+IMPORTEXPORT EXTINLINE int mpd_isoddword(mpd_uint_t word);
+/* odd coefficient */
+IMPORTEXPORT EXTINLINE int mpd_isoddcoeff(const mpd_t *dec);
+/* odd decimal, only defined for integers */
+IMPORTEXPORT int mpd_isodd(const mpd_t *dec);
+/* even decimal, only defined for integers */
+IMPORTEXPORT int mpd_iseven(const mpd_t *dec);
+/* 0 if dec is positive, 1 if dec is negative */
+IMPORTEXPORT EXTINLINE uint8_t mpd_sign(const mpd_t *dec);
+/* 1 if dec is positive, -1 if dec is negative */
+IMPORTEXPORT EXTINLINE int mpd_arith_sign(const mpd_t *dec);
+IMPORTEXPORT EXTINLINE long mpd_radix(void);
+IMPORTEXPORT EXTINLINE int mpd_isdynamic(const mpd_t *dec);
+IMPORTEXPORT EXTINLINE int mpd_isstatic(const mpd_t *dec);
+IMPORTEXPORT EXTINLINE int mpd_isdynamic_data(const mpd_t *dec);
+IMPORTEXPORT EXTINLINE int mpd_isstatic_data(const mpd_t *dec);
+IMPORTEXPORT EXTINLINE int mpd_isshared_data(const mpd_t *dec);
+IMPORTEXPORT EXTINLINE int mpd_isconst_data(const mpd_t *dec);
+IMPORTEXPORT mpd_ssize_t mpd_trail_zeros(const mpd_t *dec);
+
+
+/******************************************************************************/
+/*                       Set attributes of a decimal                          */
+/******************************************************************************/
+
+/* set number of decimal digits in the coefficient */
+IMPORTEXPORT EXTINLINE void mpd_setdigits(mpd_t *result);
+IMPORTEXPORT EXTINLINE void mpd_set_sign(mpd_t *result, uint8_t sign);
+/* copy sign from another decimal */
+IMPORTEXPORT EXTINLINE void mpd_signcpy(mpd_t *result, const mpd_t *a);
+IMPORTEXPORT EXTINLINE void mpd_set_infinity(mpd_t *result);
+IMPORTEXPORT EXTINLINE void mpd_set_qnan(mpd_t *result);
+IMPORTEXPORT EXTINLINE void mpd_set_snan(mpd_t *result);
+IMPORTEXPORT EXTINLINE void mpd_set_negative(mpd_t *result);
+IMPORTEXPORT EXTINLINE void mpd_set_positive(mpd_t *result);
+IMPORTEXPORT EXTINLINE void mpd_set_dynamic(mpd_t *result);
+IMPORTEXPORT EXTINLINE void mpd_set_static(mpd_t *result);
+IMPORTEXPORT EXTINLINE void mpd_set_dynamic_data(mpd_t *result);
+IMPORTEXPORT EXTINLINE void mpd_set_static_data(mpd_t *result);
+IMPORTEXPORT EXTINLINE void mpd_set_shared_data(mpd_t *result);
+IMPORTEXPORT EXTINLINE void mpd_set_const_data(mpd_t *result);
+IMPORTEXPORT EXTINLINE void mpd_clear_flags(mpd_t *result);
+IMPORTEXPORT EXTINLINE void mpd_set_flags(mpd_t *result, uint8_t flags);
+IMPORTEXPORT EXTINLINE void mpd_copy_flags(mpd_t *result, const mpd_t *a);
+
+
+/******************************************************************************/
+/*                              Error Macros                                  */
+/******************************************************************************/
+
+#define mpd_err_fatal(...) \
+    do {fprintf(stderr, "%s:%d: error: ", __FILE__, __LINE__); \
+        fprintf(stderr, __VA_ARGS__);  fputc('\n', stderr);    \
+        abort();                                               \
+    } while (0)
+#define mpd_err_warn(...) \
+    do {fprintf(stderr, "%s:%d: warning: ", __FILE__, __LINE__); \
+        fprintf(stderr, __VA_ARGS__); fputc('\n', stderr);       \
+    } while (0)
+
+
+/******************************************************************************/
+/*                            Memory handling                                 */
+/******************************************************************************/
+
+IMPORTEXPORT extern void *(* mpd_mallocfunc)(size_t size);
+IMPORTEXPORT extern void *(* mpd_callocfunc)(size_t nmemb, size_t size);
+IMPORTEXPORT extern void *(* mpd_reallocfunc)(void *ptr, size_t size);
+IMPORTEXPORT extern void (* mpd_free)(void *ptr);
+
+IMPORTEXPORT void *mpd_callocfunc_em(size_t nmemb, size_t size);
+
+IMPORTEXPORT void *mpd_alloc(mpd_size_t nmemb, mpd_size_t size);
+IMPORTEXPORT void *mpd_calloc(mpd_size_t nmemb, mpd_size_t size);
+IMPORTEXPORT void *mpd_realloc(void *ptr, mpd_size_t nmemb, mpd_size_t size, uint8_t *err);
+IMPORTEXPORT void *mpd_sh_alloc(mpd_size_t struct_size, mpd_size_t nmemb, mpd_size_t size);
+
+IMPORTEXPORT mpd_t *mpd_qnew(void);
+IMPORTEXPORT mpd_t *mpd_new(mpd_context_t *ctx);
+IMPORTEXPORT mpd_t *mpd_qnew_size(mpd_ssize_t size);
+IMPORTEXPORT void mpd_del(mpd_t *dec);
+
+IMPORTEXPORT void mpd_uint_zero(mpd_uint_t *dest, mpd_size_t len);
+IMPORTEXPORT int mpd_qresize(mpd_t *result, mpd_ssize_t size, uint32_t *status);
+IMPORTEXPORT int mpd_qresize_zero(mpd_t *result, mpd_ssize_t size, uint32_t *status);
+IMPORTEXPORT void mpd_minalloc(mpd_t *result);
+
+IMPORTEXPORT int mpd_resize(mpd_t *result, mpd_ssize_t size, mpd_context_t *ctx);
+IMPORTEXPORT int mpd_resize_zero(mpd_t *result, mpd_ssize_t size, mpd_context_t *ctx);
+
+
+#ifdef __cplusplus
+} /* END extern "C" */
+#endif
+
+
+#endif /* MPDECIMAL_H */
+
+
+

+ 24 - 8
mpdecimal/mpdecimal_build_log.html

@@ -4,14 +4,30 @@
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head>
 <body>
 <tt>
-Build started on: <u>03-02-2013 at 21:33.47</u><br />
-Build ended on: <u>03-02-2013 at 21:33.49</u><p />
-<b>-------------- Build: Release win32 in mpdecimal ---------------</b><br />
-i686-w64-mingw32-gcc -DCONFIG_32=1 -DPPRO=1 -DASM=1  -O3 -Wall     -c /home/mingo/dev/SquiLu/ext/mpdecimal/io.c -o /home/mingo/dev/mpdecimal-2.3/.objs-win32/io.o<br />
-i686-w64-mingw32-ar -r -s libmpdecimal-win32.a /home/mingo/dev/mpdecimal-2.3/.objs-win32/basearith.o /home/mingo/dev/mpdecimal-2.3/.objs-win32/constants.o /home/mingo/dev/mpdecimal-2.3/.objs-win32/context.o /home/mingo/dev/mpdecimal-2.3/.objs-win32/convolute.o /home/mingo/dev/mpdecimal-2.3/.objs-win32/crt.o /home/mingo/dev/mpdecimal-2.3/.objs-win32/difradix2.o /home/mingo/dev/mpdecimal-2.3/.objs-win32/fnt.o /home/mingo/dev/mpdecimal-2.3/.objs-win32/fourstep.o /home/mingo/dev/mpdecimal-2.3/.objs-win32/io.o /home/mingo/dev/mpdecimal-2.3/.objs-win32/memory.o /home/mingo/dev/mpdecimal-2.3/.objs-win32/mpdecimal.o /home/mingo/dev/mpdecimal-2.3/.objs-win32/mpsignal.o /home/mingo/dev/mpdecimal-2.3/.objs-win32/numbertheory.o /home/mingo/dev/mpdecimal-2.3/.objs-win32/sixstep.o /home/mingo/dev/mpdecimal-2.3/.objs-win32/transpose.o<br />
-Output size is 236.94 KB<br />
-<font color="#0000ff">Process terminated with status 0 (0 minutes, 1 seconds)</font><br />
-<font color="#0000ff">0 errors, 0 warnings</font><br />
+Build started on: <u>18-02-2015 at 13:51.48</u><br />
+Build ended on: <u>18-02-2015 at 13:51.55</u><p />
+<b>-------------- Build: Release_64bits in mpdecimal (compiler: GNU GCC Compiler)---------------</b><br />
+gcc -O3 -Wall -DASM=1 -DCONFIG_64=1  -c /home/mingo/dev/SquiLu/mpdecimal/basearith.c -o /home/mingo/dev/mpdecimal-2.3/.objs/basearith.o<br />
+gcc -O3 -Wall -DASM=1 -DCONFIG_64=1  -c /home/mingo/dev/SquiLu/mpdecimal/constants.c -o /home/mingo/dev/mpdecimal-2.3/.objs/constants.o<br />
+gcc -O3 -Wall -DASM=1 -DCONFIG_64=1  -c /home/mingo/dev/SquiLu/mpdecimal/context.c -o /home/mingo/dev/mpdecimal-2.3/.objs/context.o<br />
+gcc -O3 -Wall -DASM=1 -DCONFIG_64=1  -c /home/mingo/dev/SquiLu/mpdecimal/convolute.c -o /home/mingo/dev/mpdecimal-2.3/.objs/convolute.o<br />
+gcc -O3 -Wall -DASM=1 -DCONFIG_64=1  -c /home/mingo/dev/SquiLu/mpdecimal/crt.c -o /home/mingo/dev/mpdecimal-2.3/.objs/crt.o<br />
+gcc -O3 -Wall -DASM=1 -DCONFIG_64=1  -c /home/mingo/dev/SquiLu/mpdecimal/difradix2.c -o /home/mingo/dev/mpdecimal-2.3/.objs/difradix2.o<br />
+gcc -O3 -Wall -DASM=1 -DCONFIG_64=1  -c /home/mingo/dev/SquiLu/mpdecimal/fnt.c -o /home/mingo/dev/mpdecimal-2.3/.objs/fnt.o<br />
+gcc -O3 -Wall -DASM=1 -DCONFIG_64=1  -c /home/mingo/dev/SquiLu/mpdecimal/fourstep.c -o /home/mingo/dev/mpdecimal-2.3/.objs/fourstep.o<br />
+gcc -O3 -Wall -DASM=1 -DCONFIG_64=1  -c /home/mingo/dev/SquiLu/mpdecimal/io.c -o /home/mingo/dev/mpdecimal-2.3/.objs/io.o<br />
+gcc -O3 -Wall -DASM=1 -DCONFIG_64=1  -c /home/mingo/dev/SquiLu/mpdecimal/memory.c -o /home/mingo/dev/mpdecimal-2.3/.objs/memory.o<br />
+gcc -O3 -Wall -DASM=1 -DCONFIG_64=1  -c /home/mingo/dev/SquiLu/mpdecimal/mpdecimal.c -o /home/mingo/dev/mpdecimal-2.3/.objs/mpdecimal.o<br />
+gcc -O3 -Wall -DASM=1 -DCONFIG_64=1  -c /home/mingo/dev/SquiLu/mpdecimal/mpsignal.c -o /home/mingo/dev/mpdecimal-2.3/.objs/mpsignal.o<br />
+gcc -O3 -Wall -DASM=1 -DCONFIG_64=1  -c /home/mingo/dev/SquiLu/mpdecimal/numbertheory.c -o /home/mingo/dev/mpdecimal-2.3/.objs/numbertheory.o<br />
+gcc -O3 -Wall -DASM=1 -DCONFIG_64=1  -c /home/mingo/dev/SquiLu/mpdecimal/sixstep.c -o /home/mingo/dev/mpdecimal-2.3/.objs/sixstep.o<br />
+gcc -O3 -Wall -DASM=1 -DCONFIG_64=1  -c /home/mingo/dev/SquiLu/mpdecimal/transpose.c -o /home/mingo/dev/mpdecimal-2.3/.objs/transpose.o<br />
+rm -f libmpdecimal.a<br />
+ar -r -s libmpdecimal.a /home/mingo/dev/mpdecimal-2.3/.objs/basearith.o /home/mingo/dev/mpdecimal-2.3/.objs/constants.o /home/mingo/dev/mpdecimal-2.3/.objs/context.o /home/mingo/dev/mpdecimal-2.3/.objs/convolute.o /home/mingo/dev/mpdecimal-2.3/.objs/crt.o /home/mingo/dev/mpdecimal-2.3/.objs/difradix2.o /home/mingo/dev/mpdecimal-2.3/.objs/fnt.o /home/mingo/dev/mpdecimal-2.3/.objs/fourstep.o /home/mingo/dev/mpdecimal-2.3/.objs/io.o /home/mingo/dev/mpdecimal-2.3/.objs/memory.o /home/mingo/dev/mpdecimal-2.3/.objs/mpdecimal.o /home/mingo/dev/mpdecimal-2.3/.objs/mpsignal.o /home/mingo/dev/mpdecimal-2.3/.objs/numbertheory.o /home/mingo/dev/mpdecimal-2.3/.objs/sixstep.o /home/mingo/dev/mpdecimal-2.3/.objs/transpose.o<br />
+ar: creating libmpdecimal.a<br />
+Output file is libmpdecimal.a with size 352.23 KB<br />
+<font color="#0000ff">Process terminated with status 0 (0 minute(s), 7 second(s))</font><br />
+<font color="#0000ff">0 error(s), 0 warning(s) (0 minute(s), 7 second(s))</font><br />
 </tt>
 </body>
 </html>

+ 18 - 15
mpdecimal/mpsignal.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2010 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -29,6 +29,9 @@
 #include "mpdecimal.h"
 
 
+/* Signaling wrappers for the quiet functions in mpdecimal.c. */
+
+
 char *
 mpd_format(const mpd_t *dec, const char *fmt, mpd_context_t *ctx)
 {
@@ -58,7 +61,7 @@ mpd_import_u32(mpd_t *result, const uint32_t *srcdata, size_t srclen,
 }
 
 size_t
-mpd_export_u16(uint16_t *rdata, size_t rlen, uint32_t base, const mpd_t *src,
+mpd_export_u16(uint16_t **rdata, size_t rlen, uint32_t base, const mpd_t *src,
                mpd_context_t *ctx)
 {
 	size_t n;
@@ -69,7 +72,7 @@ mpd_export_u16(uint16_t *rdata, size_t rlen, uint32_t base, const mpd_t *src,
 }
 
 size_t
-mpd_export_u32(uint32_t *rdata, size_t rlen, uint32_t base, const mpd_t *src,
+mpd_export_u32(uint32_t **rdata, size_t rlen, uint32_t base, const mpd_t *src,
                mpd_context_t *ctx)
 {
 	size_t n;
@@ -245,7 +248,6 @@ mpd_get_ssize(const mpd_t *a, mpd_context_t *ctx)
 	return ret;
 }
 
-#ifdef CONFIG_32
 int32_t
 mpd_get_i32(const mpd_t *a, mpd_context_t *ctx)
 {
@@ -256,7 +258,8 @@ mpd_get_i32(const mpd_t *a, mpd_context_t *ctx)
 	mpd_addstatus_raise(ctx, status);
 	return ret;
 }
-#else
+
+#ifndef LEGACY_COMPILER
 int64_t
 mpd_get_i64(const mpd_t *a, mpd_context_t *ctx)
 {
@@ -291,7 +294,6 @@ mpd_abs_uint(const mpd_t *a, mpd_context_t *ctx)
 	return ret;
 }
 
-#ifdef CONFIG_32
 uint32_t
 mpd_get_u32(const mpd_t *a, mpd_context_t *ctx)
 {
@@ -302,7 +304,8 @@ mpd_get_u32(const mpd_t *a, mpd_context_t *ctx)
 	mpd_addstatus_raise(ctx, status);
 	return ret;
 }
-#else
+
+#ifndef LEGACY_COMPILER
 uint64_t
 mpd_get_u64(const mpd_t *a, mpd_context_t *ctx)
 {
@@ -518,7 +521,7 @@ mpd_add_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx)
 	mpd_addstatus_raise(ctx, status);
 }
 
-#ifdef CONFIG_64
+#ifndef LEGACY_COMPILER
 void
 mpd_add_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx)
 {
@@ -544,7 +547,7 @@ mpd_add_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx)
 	mpd_addstatus_raise(ctx, status);
 }
 
-#ifdef CONFIG_64
+#ifndef LEGACY_COMPILER
 void
 mpd_add_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx)
 {
@@ -570,7 +573,7 @@ mpd_sub_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx)
 	mpd_addstatus_raise(ctx, status);
 }
 
-#ifdef CONFIG_64
+#ifndef LEGACY_COMPILER
 void
 mpd_sub_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx)
 {
@@ -596,7 +599,7 @@ mpd_sub_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx)
 	mpd_addstatus_raise(ctx, status);
 }
 
-#ifdef CONFIG_64
+#ifndef LEGACY_COMPILER
 void
 mpd_sub_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx)
 {
@@ -630,7 +633,7 @@ mpd_div_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx)
 	mpd_addstatus_raise(ctx, status);
 }
 
-#ifdef CONFIG_64
+#ifndef LEGACY_COMPILER
 void
 mpd_div_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx)
 {
@@ -656,7 +659,7 @@ mpd_div_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx)
 	mpd_addstatus_raise(ctx, status);
 }
 
-#ifdef CONFIG_64
+#ifndef LEGACY_COMPILER
 void
 mpd_div_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx)
 {
@@ -779,7 +782,7 @@ mpd_mul_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx)
 	mpd_addstatus_raise(ctx, status);
 }
 
-#ifdef CONFIG_64
+#ifndef LEGACY_COMPILER
 void
 mpd_mul_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx)
 {
@@ -805,7 +808,7 @@ mpd_mul_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx)
 	mpd_addstatus_raise(ctx, status);
 }
 
-#ifdef CONFIG_64
+#ifndef LEGACY_COMPILER
 void
 mpd_mul_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx)
 {

+ 71 - 58
mpdecimal/numbertheory.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2010 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -34,86 +34,99 @@
 #include "numbertheory.h"
 
 
-/* transform kernel */
+/* Bignum: Initialize the Number Theoretic Transform. */
+
+
+/*
+ * Return the nth root of unity in F(p). This corresponds to e**((2*pi*i)/n)
+ * in the Fourier transform. We have w**n == 1 (mod p).
+ *    n := transform length.
+ *    sign := -1 for forward transform, 1 for backward transform.
+ *    modnum := one of {P1, P2, P3}.
+ */
 mpd_uint_t
 _mpd_getkernel(mpd_uint_t n, int sign, int modnum)
 {
-	mpd_uint_t umod, p, r, xi;
+    mpd_uint_t umod, p, r, xi;
 #ifdef PPRO
-	double dmod;
-	uint32_t dinvmod[3];
+    double dmod;
+    uint32_t dinvmod[3];
 #endif
 
-	SETMODULUS(modnum);
-	r = mpd_roots[modnum];
-	p = umod;
-	xi = (p-1) / n;
+    SETMODULUS(modnum);
+    r = mpd_roots[modnum]; /* primitive root of F(p) */
+    p = umod;
+    xi = (p-1) / n;
 
-	if (sign == -1)
-		return POWMOD(r, (p-1-xi));
-	else
-		return POWMOD(r, xi);
+    if (sign == -1)
+        return POWMOD(r, (p-1-xi));
+    else
+        return POWMOD(r, xi);
 }
 
-/* initialize transform parameters */
+/*
+ * Initialize and return transform parameters.
+ *    n := transform length.
+ *    sign := -1 for forward transform, 1 for backward transform.
+ *    modnum := one of {P1, P2, P3}.
+ */
 struct fnt_params *
 _mpd_init_fnt_params(mpd_size_t n, int sign, int modnum)
 {
-	struct fnt_params *tparams;
-	mpd_uint_t umod;
+    struct fnt_params *tparams;
+    mpd_uint_t umod;
 #ifdef PPRO
-	double dmod;
-	uint32_t dinvmod[3];
+    double dmod;
+    uint32_t dinvmod[3];
 #endif
-	mpd_uint_t kernel, imag, w;
-	mpd_uint_t i;
-	mpd_size_t nhalf;
-
-	assert(ispower2(n));
-	assert(sign == -1 || sign == 1);
-	assert(P1 <= modnum && modnum <= P3);
-
-	nhalf = n/2;
-	tparams = mpd_sh_alloc(sizeof *tparams, nhalf, sizeof (mpd_uint_t));
-	if (tparams == NULL) {
-		return NULL;
-	}
-
-	SETMODULUS(modnum);
-	kernel = _mpd_getkernel(n, sign, modnum);
-	imag = _mpd_getkernel(4, -sign, modnum);
-
-	tparams->modnum = modnum;
-	tparams->modulus = umod;
-	tparams->imag = imag;
-	tparams->kernel = kernel;
-
-	w  = 1;
-	for (i = 0; i < nhalf; i++) {
-		tparams->wtable[i] = w;
-		w = MULMOD(w, kernel);
-	}
-
-	return tparams;
+    mpd_uint_t kernel, w;
+    mpd_uint_t i;
+    mpd_size_t nhalf;
+
+    assert(ispower2(n));
+    assert(sign == -1 || sign == 1);
+    assert(P1 <= modnum && modnum <= P3);
+
+    nhalf = n/2;
+    tparams = mpd_sh_alloc(sizeof *tparams, nhalf, sizeof (mpd_uint_t));
+    if (tparams == NULL) {
+        return NULL;
+    }
+
+    SETMODULUS(modnum);
+    kernel = _mpd_getkernel(n, sign, modnum);
+
+    tparams->modnum = modnum;
+    tparams->modulus = umod;
+    tparams->kernel = kernel;
+
+    /* wtable[] := w**0, w**1, ..., w**(nhalf-1) */
+    w = 1;
+    for (i = 0; i < nhalf; i++) {
+        tparams->wtable[i] = w;
+        w = MULMOD(w, kernel);
+    }
+
+    return tparams;
 }
 
-/* initialize wtable of size three */
+/* Initialize wtable of size three. */
 void
 _mpd_init_w3table(mpd_uint_t w3table[3], int sign, int modnum)
 {
-	mpd_uint_t umod;
+    mpd_uint_t umod;
 #ifdef PPRO
-	double dmod;
-	uint32_t dinvmod[3];
+    double dmod;
+    uint32_t dinvmod[3];
 #endif
-	mpd_uint_t kernel;
+    mpd_uint_t kernel;
 
-	SETMODULUS(modnum);
-	kernel = _mpd_getkernel(3, sign, modnum);
+    SETMODULUS(modnum);
+    kernel = _mpd_getkernel(3, sign, modnum);
 
-	w3table[0] = 1;
-	w3table[1] = kernel;
-	w3table[2] = POWMOD(kernel, 2);
+    w3table[0] = 1;
+    w3table[1] = kernel;
+    w3table[2] = POWMOD(kernel, 2);
 }
 
 

+ 17 - 11
mpdecimal/numbertheory.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2010 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -34,13 +34,16 @@
 #include "mpdecimal.h"
 
 
+/* Internal header file: all symbols have local scope in the DSO */
+MPD_PRAGMA(MPD_HIDE_SYMBOLS_START)
+
+
 /* transform parameters */
 struct fnt_params {
-	int modnum;
-	mpd_uint_t modulus;
-	mpd_uint_t imag;
-	mpd_uint_t kernel;
-	mpd_uint_t wtable[];
+    int modnum;
+    mpd_uint_t modulus;
+    mpd_uint_t kernel;
+    mpd_uint_t wtable[];
 };
 
 
@@ -53,20 +56,23 @@ void _mpd_init_w3table(mpd_uint_t w3table[3], int sign, int modnum);
 static inline void
 ppro_setmodulus(int modnum, mpd_uint_t *umod, double *dmod, uint32_t dinvmod[3])
 {
-	*dmod = *umod =  mpd_moduli[modnum];
-	dinvmod[0] = mpd_invmoduli[modnum][0];
-	dinvmod[1] = mpd_invmoduli[modnum][1];
-	dinvmod[2] = mpd_invmoduli[modnum][2];
+    *dmod = *umod =  mpd_moduli[modnum];
+    dinvmod[0] = mpd_invmoduli[modnum][0];
+    dinvmod[1] = mpd_invmoduli[modnum][1];
+    dinvmod[2] = mpd_invmoduli[modnum][2];
 }
 #else
 static inline void
 std_setmodulus(int modnum, mpd_uint_t *umod)
 {
-	*umod =  mpd_moduli[modnum];
+    *umod =  mpd_moduli[modnum];
 }
 #endif
 
 
+MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
+
+
 #endif
 
 

+ 143 - 148
mpdecimal/sixstep.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2010 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -32,105 +32,98 @@
 #include <assert.h>
 #include "bits.h"
 #include "difradix2.h"
-#include "mptypes.h"
 #include "numbertheory.h"
 #include "transpose.h"
 #include "umodarith.h"
 #include "sixstep.h"
 
 
-/*
- * A variant of the six-step algorithm from:
- *
- * David H. Bailey: FFTs in External or Hierarchical Memory, Journal of
- * Supercomputing, vol. 4, no. 1 (March 1990), p. 23-35.
- *
- * URL: http://crd.lbl.gov/~dhbailey/dhbpapers/
- */
+/* Bignum: Cache efficient Matrix Fourier Transform for arrays of the
+   form 2**n (See literature/six-step.txt). */
 
 
 /* forward transform with sign = -1 */
 int
 six_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum)
 {
-	struct fnt_params *tparams;
-	mpd_size_t log2n, C, R;
-	mpd_uint_t kernel;
-	mpd_uint_t umod;
+    struct fnt_params *tparams;
+    mpd_size_t log2n, C, R;
+    mpd_uint_t kernel;
+    mpd_uint_t umod;
 #ifdef PPRO
-	double dmod;
-	uint32_t dinvmod[3];
+    double dmod;
+    uint32_t dinvmod[3];
 #endif
-	mpd_uint_t *x, w0, w1, wstep;
-	mpd_size_t i, k;
-
-
-	assert(ispower2(n));
-	assert(n >= 16);
-	assert(n <= MPD_MAXTRANSFORM_2N);
-
-	log2n = mpd_bsr(n);
-	C = (ONE_UM << (log2n / 2));  /* number of columns */
-	R = (ONE_UM << (log2n - (log2n / 2))); /* number of rows */
-
-
-	/* view 'a' as an RxC matrix, transpose */
-	if (!transpose_pow2(a, R, C)) {
-		return 0;
-	}
-
-	if ((tparams = _mpd_init_fnt_params(R, -1, modnum)) == NULL) {
-		return 0;
-	}
-	for (x = a; x < a+n; x += R) {
-		fnt_dif2(x, R, tparams);
-	}
-
-	if (!transpose_pow2(a, C, R)) {
-		mpd_free(tparams);
-		return 0;
-	}
-
-
-	SETMODULUS(modnum);
-	kernel = _mpd_getkernel(n, -1, modnum);
-	for (i = 1; i < R; i++) {
-		w0 = 1;
-		w1 = POWMOD(kernel, i);
-		wstep = MULMOD(w1, w1);
-		for (k = 0; k < C; k += 2) {
-			mpd_uint_t x0 = a[i*C+k];
-			mpd_uint_t x1 = a[i*C+k+1];
-			MULMOD2(&x0, w0, &x1, w1);
-			MULMOD2C(&w0, &w1, wstep);
-			a[i*C+k] = x0;
-			a[i*C+k+1] = x1;
-		}
-	}
-
-
-	if (C != R) {
-		mpd_free(tparams);
-		if ((tparams = _mpd_init_fnt_params(C, -1, modnum)) == NULL) {
-			return 0;
-		}
-	}
-	for (x = a; x < a+n; x += C) {
-		fnt_dif2(x, C, tparams);
-	}
-	mpd_free(tparams);
-
+    mpd_uint_t *x, w0, w1, wstep;
+    mpd_size_t i, k;
+
+
+    assert(ispower2(n));
+    assert(n >= 16);
+    assert(n <= MPD_MAXTRANSFORM_2N);
+
+    log2n = mpd_bsr(n);
+    C = ((mpd_size_t)1) << (log2n / 2);  /* number of columns */
+    R = ((mpd_size_t)1) << (log2n - (log2n / 2)); /* number of rows */
+
+
+    /* Transpose the matrix. */
+    if (!transpose_pow2(a, R, C)) {
+        return 0;
+    }
+
+    /* Length R transform on the rows. */
+    if ((tparams = _mpd_init_fnt_params(R, -1, modnum)) == NULL) {
+        return 0;
+    }
+    for (x = a; x < a+n; x += R) {
+        fnt_dif2(x, R, tparams);
+    }
+
+    /* Transpose the matrix. */
+    if (!transpose_pow2(a, C, R)) {
+        mpd_free(tparams);
+        return 0;
+    }
+
+    /* Multiply each matrix element (addressed by i*C+k) by r**(i*k). */
+    SETMODULUS(modnum);
+    kernel = _mpd_getkernel(n, -1, modnum);
+    for (i = 1; i < R; i++) {
+        w0 = 1;                  /* r**(i*0): initial value for k=0 */
+        w1 = POWMOD(kernel, i);  /* r**(i*1): initial value for k=1 */
+        wstep = MULMOD(w1, w1);  /* r**(2*i) */
+        for (k = 0; k < C; k += 2) {
+            mpd_uint_t x0 = a[i*C+k];
+            mpd_uint_t x1 = a[i*C+k+1];
+            MULMOD2(&x0, w0, &x1, w1);
+            MULMOD2C(&w0, &w1, wstep);  /* r**(i*(k+2)) = r**(i*k) * r**(2*i) */
+            a[i*C+k] = x0;
+            a[i*C+k+1] = x1;
+        }
+    }
+
+    /* Length C transform on the rows. */
+    if (C != R) {
+        mpd_free(tparams);
+        if ((tparams = _mpd_init_fnt_params(C, -1, modnum)) == NULL) {
+            return 0;
+        }
+    }
+    for (x = a; x < a+n; x += C) {
+        fnt_dif2(x, C, tparams);
+    }
+    mpd_free(tparams);
 
 #if 0
-	/* An unordered transform is sufficient for convolution. */
-	if (ordered) {
-		if (!transpose_pow2(a, R, C)) {
-			return 0;
-		}
-	}
+    /* An unordered transform is sufficient for convolution. */
+    /* Transpose the matrix. */
+    if (!transpose_pow2(a, R, C)) {
+        return 0;
+    }
 #endif
 
-	return 1;
+    return 1;
 }
 
 
@@ -138,82 +131,84 @@ six_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum)
 int
 inv_six_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum)
 {
-	struct fnt_params *tparams;
-	mpd_size_t log2n, C, R;
-	mpd_uint_t kernel;
-	mpd_uint_t umod;
+    struct fnt_params *tparams;
+    mpd_size_t log2n, C, R;
+    mpd_uint_t kernel;
+    mpd_uint_t umod;
 #ifdef PPRO
-	double dmod;
-	uint32_t dinvmod[3];
+    double dmod;
+    uint32_t dinvmod[3];
 #endif
-	mpd_uint_t *x, w0, w1, wstep;
-	mpd_size_t i, k;
+    mpd_uint_t *x, w0, w1, wstep;
+    mpd_size_t i, k;
 
 
-	assert(ispower2(n));
-	assert(n >= 16);
-	assert(n <= MPD_MAXTRANSFORM_2N);
+    assert(ispower2(n));
+    assert(n >= 16);
+    assert(n <= MPD_MAXTRANSFORM_2N);
 
-	log2n = mpd_bsr(n);
-	C = (ONE_UM << (log2n / 2)); /* number of columns */
-	R = (ONE_UM << (log2n - (log2n / 2))); /* number of rows */
+    log2n = mpd_bsr(n);
+    C = ((mpd_size_t)1) << (log2n / 2); /* number of columns */
+    R = ((mpd_size_t)1) << (log2n - (log2n / 2)); /* number of rows */
 
 
 #if 0
-	/* An unordered transform is sufficient for convolution. */
-	if (ordered) {
-		if (!transpose_pow2(a, C, R)) {
-			return 0;
-		}
-	}
+    /* An unordered transform is sufficient for convolution. */
+    /* Transpose the matrix, producing an R*C matrix. */
+    if (!transpose_pow2(a, C, R)) {
+        return 0;
+    }
 #endif
 
-	if ((tparams = _mpd_init_fnt_params(C, 1, modnum)) == NULL) {
-		return 0;
-	}
-	for (x = a; x < a+n; x += C) {
-		fnt_dif2(x, C, tparams);
-	}
-
-	if (!transpose_pow2(a, R, C)) {
-		mpd_free(tparams);
-		return 0;
-	}
-
-
-	SETMODULUS(modnum);
-	kernel = _mpd_getkernel(n, 1, modnum);
-	for (i = 1; i < C; i++) {
-		w0 = 1;
-		w1 = POWMOD(kernel, i);
-		wstep = MULMOD(w1, w1);
-		for (k = 0; k < R; k += 2) {
-			mpd_uint_t x0 = a[i*R+k];
-			mpd_uint_t x1 = a[i*R+k+1];
-			MULMOD2(&x0, w0, &x1, w1);
-			MULMOD2C(&w0, &w1, wstep);
-			a[i*R+k] = x0;
-			a[i*R+k+1] = x1;
-		}
-	}
-
-
-	if (R != C) {
-		mpd_free(tparams);
-		if ((tparams = _mpd_init_fnt_params(R, 1, modnum)) == NULL) {
-			return 0;
-		}
-	}
-	for (x = a; x < a+n; x += R) {
-		fnt_dif2(x, R, tparams);
-	}
-	mpd_free(tparams);
-
-	if (!transpose_pow2(a, C, R)) {
-		return 0;
-	}
-
-	return 1;
+    /* Length C transform on the rows. */
+    if ((tparams = _mpd_init_fnt_params(C, 1, modnum)) == NULL) {
+        return 0;
+    }
+    for (x = a; x < a+n; x += C) {
+        fnt_dif2(x, C, tparams);
+    }
+
+    /* Multiply each matrix element (addressed by i*C+k) by r**(i*k). */
+    SETMODULUS(modnum);
+    kernel = _mpd_getkernel(n, 1, modnum);
+    for (i = 1; i < R; i++) {
+        w0 = 1;
+        w1 = POWMOD(kernel, i);
+        wstep = MULMOD(w1, w1);
+        for (k = 0; k < C; k += 2) {
+            mpd_uint_t x0 = a[i*C+k];
+            mpd_uint_t x1 = a[i*C+k+1];
+            MULMOD2(&x0, w0, &x1, w1);
+            MULMOD2C(&w0, &w1, wstep);
+            a[i*C+k] = x0;
+            a[i*C+k+1] = x1;
+        }
+    }
+
+    /* Transpose the matrix. */
+    if (!transpose_pow2(a, R, C)) {
+        mpd_free(tparams);
+        return 0;
+    }
+
+    /* Length R transform on the rows. */
+    if (R != C) {
+        mpd_free(tparams);
+        if ((tparams = _mpd_init_fnt_params(R, 1, modnum)) == NULL) {
+            return 0;
+        }
+    }
+    for (x = a; x < a+n; x += R) {
+        fnt_dif2(x, R, tparams);
+    }
+    mpd_free(tparams);
+
+    /* Transpose the matrix. */
+    if (!transpose_pow2(a, C, R)) {
+        return 0;
+    }
+
+    return 1;
 }
 
 

+ 8 - 1
mpdecimal/sixstep.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2010 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -34,8 +34,15 @@
 #include <stdio.h>
 
 
+/* Internal header file: all symbols have local scope in the DSO */
+MPD_PRAGMA(MPD_HIDE_SYMBOLS_START)
+
+
 int six_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum);
 int inv_six_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum);
 
 
+MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
+
+
 #endif

+ 172 - 168
mpdecimal/transpose.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2010 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -42,22 +42,26 @@
 #define SIDE 128
 
 
+/* Bignum: The transpose functions are used for very large transforms
+   in sixstep.c and fourstep.c. */
+
+
 /* Definition of the matrix transpose */
 void
 std_trans(mpd_uint_t dest[], mpd_uint_t src[], mpd_size_t rows, mpd_size_t cols)
 {
-	mpd_size_t idest, isrc;
-	mpd_size_t r, c;
-
-	for (r = 0; r < rows; r++) {
-		isrc = r * cols;
-		idest = r;
-		for (c = 0; c < cols; c++) {
-			dest[idest] = src[isrc];
-			isrc += 1;
-			idest += rows;
-		}
-	}
+    mpd_size_t idest, isrc;
+    mpd_size_t r, c;
+
+    for (r = 0; r < rows; r++) {
+        isrc = r * cols;
+        idest = r;
+        for (c = 0; c < cols; c++) {
+            dest[idest] = src[isrc];
+            isrc += 1;
+            idest += rows;
+        }
+    }
 }
 
 /*
@@ -68,168 +72,168 @@ std_trans(mpd_uint_t dest[], mpd_uint_t src[], mpd_size_t rows, mpd_size_t cols)
 static int
 swap_halfrows_pow2(mpd_uint_t *matrix, mpd_size_t rows, mpd_size_t cols, int dir)
 {
-	mpd_uint_t buf1[BUFSIZE];
-	mpd_uint_t buf2[BUFSIZE];
-	mpd_uint_t *readbuf, *writebuf, *hp;
-	mpd_size_t *done, dbits;
-	mpd_size_t b = BUFSIZE, stride;
-	mpd_size_t hn, hmax; /* halfrow number */
-	mpd_size_t m, r=0;
-	mpd_size_t offset;
-	mpd_size_t next;
+    mpd_uint_t buf1[BUFSIZE];
+    mpd_uint_t buf2[BUFSIZE];
+    mpd_uint_t *readbuf, *writebuf, *hp;
+    mpd_size_t *done, dbits;
+    mpd_size_t b = BUFSIZE, stride;
+    mpd_size_t hn, hmax; /* halfrow number */
+    mpd_size_t m, r=0;
+    mpd_size_t offset;
+    mpd_size_t next;
 
 
-	assert(cols == mul_size_t(2, rows));
+    assert(cols == mul_size_t(2, rows));
 
-	if (dir == FORWARD_CYCLE) {
-		r = rows;
-	}
-	else if (dir == BACKWARD_CYCLE) {
-		r = 2;
-	}
-	else {
-		abort(); /* GCOV_NOT_REACHED */
-	}
+    if (dir == FORWARD_CYCLE) {
+        r = rows;
+    }
+    else if (dir == BACKWARD_CYCLE) {
+        r = 2;
+    }
+    else {
+        abort(); /* GCOV_NOT_REACHED */
+    }
 
-	m = cols - 1;
-	hmax = rows; /* cycles start at odd halfrows */
-	dbits = 8 * sizeof *done;
-	if ((done = mpd_calloc(hmax/(sizeof *done) + 1, sizeof *done)) == NULL) {
-		return 0;
-	}
+    m = cols - 1;
+    hmax = rows; /* cycles start at odd halfrows */
+    dbits = 8 * sizeof *done;
+    if ((done = mpd_calloc(hmax/(sizeof *done) + 1, sizeof *done)) == NULL) {
+        return 0;
+    }
 
-	for (hn = 1; hn <= hmax; hn += 2) {
+    for (hn = 1; hn <= hmax; hn += 2) {
 
-		if (done[hn/dbits] & mpd_bits[hn%dbits]) {
-			continue;
-		}
+        if (done[hn/dbits] & mpd_bits[hn%dbits]) {
+            continue;
+        }
 
-		readbuf = buf1; writebuf = buf2;
+        readbuf = buf1; writebuf = buf2;
 
-		for (offset = 0; offset < cols/2; offset += b) {
+        for (offset = 0; offset < cols/2; offset += b) {
 
-			stride = (offset + b < cols/2) ? b : cols/2-offset;
+            stride = (offset + b < cols/2) ? b : cols/2-offset;
 
-			hp = matrix + hn*cols/2;
-			memcpy(readbuf, hp+offset, stride*(sizeof *readbuf));
-			pointerswap(&readbuf, &writebuf);
+            hp = matrix + hn*cols/2;
+            memcpy(readbuf, hp+offset, stride*(sizeof *readbuf));
+            pointerswap(&readbuf, &writebuf);
 
-			next = mulmod_size_t(hn, r, m);
-			hp = matrix + next*cols/2;
+            next = mulmod_size_t(hn, r, m);
+            hp = matrix + next*cols/2;
 
-			while (next != hn) {
+            while (next != hn) {
 
-				memcpy(readbuf, hp+offset, stride*(sizeof *readbuf));
-				memcpy(hp+offset, writebuf, stride*(sizeof *writebuf));
-				pointerswap(&readbuf, &writebuf);
+                memcpy(readbuf, hp+offset, stride*(sizeof *readbuf));
+                memcpy(hp+offset, writebuf, stride*(sizeof *writebuf));
+                pointerswap(&readbuf, &writebuf);
 
-				done[next/dbits] |= mpd_bits[next%dbits];
+                done[next/dbits] |= mpd_bits[next%dbits];
 
-				next = mulmod_size_t(next, r, m);
-			        hp = matrix + next*cols/2;
+                next = mulmod_size_t(next, r, m);
+                    hp = matrix + next*cols/2;
 
-			}
+            }
 
-			memcpy(hp+offset, writebuf, stride*(sizeof *writebuf));
+            memcpy(hp+offset, writebuf, stride*(sizeof *writebuf));
 
-			done[hn/dbits] |= mpd_bits[hn%dbits];
-		}
-	}
+            done[hn/dbits] |= mpd_bits[hn%dbits];
+        }
+    }
 
-	mpd_free(done);
-	return 1;
+    mpd_free(done);
+    return 1;
 }
 
 /* In-place transpose of a square matrix */
 static inline void
 squaretrans(mpd_uint_t *buf, mpd_size_t cols)
 {
-	mpd_uint_t tmp;
-	mpd_size_t idest, isrc;
-	mpd_size_t r, c;
-
-	for (r = 0; r < cols; r++) {
-		c = r+1;
-		isrc = r*cols + c;
-		idest = c*cols + r;
-		for (c = r+1; c < cols; c++) {
-			tmp = buf[isrc];
-			buf[isrc] = buf[idest];
-			buf[idest] = tmp;
-			isrc += 1;
-			idest += cols;
-		}
-	}
+    mpd_uint_t tmp;
+    mpd_size_t idest, isrc;
+    mpd_size_t r, c;
+
+    for (r = 0; r < cols; r++) {
+        c = r+1;
+        isrc = r*cols + c;
+        idest = c*cols + r;
+        for (c = r+1; c < cols; c++) {
+            tmp = buf[isrc];
+            buf[isrc] = buf[idest];
+            buf[idest] = tmp;
+            isrc += 1;
+            idest += cols;
+        }
+    }
 }
 
 /*
  * Transpose 2^n * 2^n matrix. For cache efficiency, the matrix is split into
  * square blocks with side length 'SIDE'. First, the blocks are transposed,
- * then a square tranposition is done on each individual block.
+ * then a square transposition is done on each individual block.
  */
 static void
 squaretrans_pow2(mpd_uint_t *matrix, mpd_size_t size)
 {
-	mpd_uint_t buf1[SIDE*SIDE];
-	mpd_uint_t buf2[SIDE*SIDE];
-	mpd_uint_t *to, *from;
-	mpd_size_t b = size;
-	mpd_size_t r, c;
-	mpd_size_t i;
-
-	while (b > SIDE) b >>= 1;
-
-	for (r = 0; r < size; r += b) {
-
-		for (c = r; c < size; c += b) {
-
-			from = matrix + r*size + c;
-			to = buf1;
-			for (i = 0; i < b; i++) {
-				memcpy(to, from, b*(sizeof *to));
-				from += size;
-				to += b;
-			}
-			squaretrans(buf1, b);
-
-			if (r == c) {
-				to = matrix + r*size + c;
-				from = buf1;
-				for (i = 0; i < b; i++) {
-					memcpy(to, from, b*(sizeof *to));
-					from += b;
-					to += size;
-				}
-				continue;
-			}
-			else {
-				from = matrix + c*size + r;
-				to = buf2;
-				for (i = 0; i < b; i++) {
-					memcpy(to, from, b*(sizeof *to));
-					from += size;
-					to += b;
-				}
-				squaretrans(buf2, b);
-
-				to = matrix + c*size + r;
-				from = buf1;
-				for (i = 0; i < b; i++) {
-					memcpy(to, from, b*(sizeof *to));
-					from += b;
-					to += size;
-				}
-
-				to = matrix + r*size + c;
-				from = buf2;
-				for (i = 0; i < b; i++) {
-					memcpy(to, from, b*(sizeof *to));
-					from += b;
-					to += size;
-				}
-			}
-		}
-	}
+    mpd_uint_t buf1[SIDE*SIDE];
+    mpd_uint_t buf2[SIDE*SIDE];
+    mpd_uint_t *to, *from;
+    mpd_size_t b = size;
+    mpd_size_t r, c;
+    mpd_size_t i;
+
+    while (b > SIDE) b >>= 1;
+
+    for (r = 0; r < size; r += b) {
+
+        for (c = r; c < size; c += b) {
+
+            from = matrix + r*size + c;
+            to = buf1;
+            for (i = 0; i < b; i++) {
+                memcpy(to, from, b*(sizeof *to));
+                from += size;
+                to += b;
+            }
+            squaretrans(buf1, b);
+
+            if (r == c) {
+                to = matrix + r*size + c;
+                from = buf1;
+                for (i = 0; i < b; i++) {
+                    memcpy(to, from, b*(sizeof *to));
+                    from += b;
+                    to += size;
+                }
+                continue;
+            }
+            else {
+                from = matrix + c*size + r;
+                to = buf2;
+                for (i = 0; i < b; i++) {
+                    memcpy(to, from, b*(sizeof *to));
+                    from += size;
+                    to += b;
+                }
+                squaretrans(buf2, b);
+
+                to = matrix + c*size + r;
+                from = buf1;
+                for (i = 0; i < b; i++) {
+                    memcpy(to, from, b*(sizeof *to));
+                    from += b;
+                    to += size;
+                }
+
+                to = matrix + r*size + c;
+                from = buf2;
+                for (i = 0; i < b; i++) {
+                    memcpy(to, from, b*(sizeof *to));
+                    from += b;
+                    to += size;
+                }
+            }
+        }
+    }
 
 }
 
@@ -240,33 +244,33 @@ squaretrans_pow2(mpd_uint_t *matrix, mpd_size_t size)
 int
 transpose_pow2(mpd_uint_t *matrix, mpd_size_t rows, mpd_size_t cols)
 {
-	mpd_size_t size = mul_size_t(rows, cols);
-
-	assert(ispower2(rows));
-	assert(ispower2(cols));
-
-	if (cols == rows) {
-		squaretrans_pow2(matrix, rows);
-	}
-	else if (cols == mul_size_t(2, rows)) {
-		if (!swap_halfrows_pow2(matrix, rows, cols, FORWARD_CYCLE)) {
-			return 0;
-		}
-		squaretrans_pow2(matrix, rows);
-		squaretrans_pow2(matrix+(size/2), rows);
-	}
-	else if (rows == mul_size_t(2, cols)) {
-		squaretrans_pow2(matrix, cols);
-		squaretrans_pow2(matrix+(size/2), cols);
-		if (!swap_halfrows_pow2(matrix, cols, rows, BACKWARD_CYCLE)) {
-			return 0;
-		}
-	}
-	else {
-		abort(); /* GCOV_NOT_REACHED */
-	}
-
-	return 1;
+    mpd_size_t size = mul_size_t(rows, cols);
+
+    assert(ispower2(rows));
+    assert(ispower2(cols));
+
+    if (cols == rows) {
+        squaretrans_pow2(matrix, rows);
+    }
+    else if (cols == mul_size_t(2, rows)) {
+        if (!swap_halfrows_pow2(matrix, rows, cols, FORWARD_CYCLE)) {
+            return 0;
+        }
+        squaretrans_pow2(matrix, rows);
+        squaretrans_pow2(matrix+(size/2), rows);
+    }
+    else if (rows == mul_size_t(2, cols)) {
+        squaretrans_pow2(matrix, cols);
+        squaretrans_pow2(matrix+(size/2), cols);
+        if (!swap_halfrows_pow2(matrix, cols, rows, BACKWARD_CYCLE)) {
+            return 0;
+        }
+    }
+    else {
+        abort(); /* GCOV_NOT_REACHED */
+    }
+
+    return 1;
 }
 
 

+ 12 - 5
mpdecimal/transpose.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2010 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -34,6 +34,10 @@
 #include <stdio.h>
 
 
+/* Internal header file: all symbols have local scope in the DSO */
+MPD_PRAGMA(MPD_HIDE_SYMBOLS_START)
+
+
 enum {FORWARD_CYCLE, BACKWARD_CYCLE};
 
 
@@ -44,12 +48,15 @@ void transpose_3xpow2(mpd_uint_t *matrix, mpd_size_t rows, mpd_size_t cols);
 
 static inline void pointerswap(mpd_uint_t **a, mpd_uint_t **b)
 {
-	mpd_uint_t *tmp;
+    mpd_uint_t *tmp;
 
-	tmp = *b;
-	*b = *a;
-	*a = tmp;
+    tmp = *b;
+    *b = *a;
+    *a = tmp;
 }
 
 
+MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
+
+
 #endif

+ 375 - 345
mpdecimal/typearith.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2010 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -34,7 +34,7 @@
 
 
 /*****************************************************************************/
-/*                      Native arithmetic on basic types                     */
+/*                 Low level native arithmetic on basic types                */
 /*****************************************************************************/
 
 
@@ -49,53 +49,53 @@
 static inline void
 _mpd_mul_words(mpd_uint_t *hi, mpd_uint_t *lo, mpd_uint_t a, mpd_uint_t b)
 {
-	__uint128_t hl;
+    __uint128_t hl;
 
-	hl = (__uint128_t)a * b;
+    hl = (__uint128_t)a * b;
 
-	*hi = hl >> 64;
-	*lo = (mpd_uint_t)hl;
+    *hi = hl >> 64;
+    *lo = (mpd_uint_t)hl;
 }
 
 static inline void
 _mpd_div_words(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t hi, mpd_uint_t lo,
                mpd_uint_t d)
 {
-	__uint128_t hl;
+    __uint128_t hl;
 
-	hl = ((__uint128_t)hi<<64) + lo;
-	*q = (mpd_uint_t)(hl / d); /* quotient is known to fit */
-	*r = (mpd_uint_t)(hl - (__uint128_t)(*q) * d);
+    hl = ((__uint128_t)hi<<64) + lo;
+    *q = (mpd_uint_t)(hl / d); /* quotient is known to fit */
+    *r = (mpd_uint_t)(hl - (__uint128_t)(*q) * d);
 }
 #else
 static inline void
 _mpd_mul_words(mpd_uint_t *hi, mpd_uint_t *lo, mpd_uint_t a, mpd_uint_t b)
 {
-	uint32_t w[4], carry;
-	uint32_t ah, al, bh, bl;
-	uint64_t hl;
+    uint32_t w[4], carry;
+    uint32_t ah, al, bh, bl;
+    uint64_t hl;
 
-	ah = (uint32_t)(a>>32); al = (uint32_t)a;
-	bh = (uint32_t)(b>>32); bl = (uint32_t)b;
+    ah = (uint32_t)(a>>32); al = (uint32_t)a;
+    bh = (uint32_t)(b>>32); bl = (uint32_t)b;
 
-	hl = (uint64_t)al * bl;
-	w[0] = (uint32_t)hl;
-	carry = (uint32_t)(hl>>32);
+    hl = (uint64_t)al * bl;
+    w[0] = (uint32_t)hl;
+    carry = (uint32_t)(hl>>32);
 
-	hl = (uint64_t)ah * bl + carry;
-	w[1] = (uint32_t)hl;
-	w[2] = (uint32_t)(hl>>32);
+    hl = (uint64_t)ah * bl + carry;
+    w[1] = (uint32_t)hl;
+    w[2] = (uint32_t)(hl>>32);
 
-	hl = (uint64_t)al * bh + w[1];
-	w[1] = (uint32_t)hl;
-	carry = (uint32_t)(hl>>32);
+    hl = (uint64_t)al * bh + w[1];
+    w[1] = (uint32_t)hl;
+    carry = (uint32_t)(hl>>32);
 
-	hl = ((uint64_t)ah * bh + w[2]) + carry;
-	w[2] = (uint32_t)hl;
-	w[3] = (uint32_t)(hl>>32);
+    hl = ((uint64_t)ah * bh + w[2]) + carry;
+    w[2] = (uint32_t)hl;
+    w[3] = (uint32_t)(hl>>32);
 
-	*hi = ((uint64_t)w[3]<<32) + w[2];
-	*lo = ((uint64_t)w[1]<<32) + w[0];
+    *hi = ((uint64_t)w[3]<<32) + w[2];
+    *lo = ((uint64_t)w[1]<<32) + w[0];
 }
 
 /*
@@ -109,94 +109,94 @@ _mpd_mul_words(mpd_uint_t *hi, mpd_uint_t *lo, mpd_uint_t a, mpd_uint_t b)
 static inline int
 nlz(uint64_t x)
 {
-	int n;
+    int n;
 
-	if (x == 0) return(64);
+    if (x == 0) return(64);
 
-	n = 0;
-	if (x <= 0x00000000FFFFFFFF) {n = n +32; x = x <<32;}
-	if (x <= 0x0000FFFFFFFFFFFF) {n = n +16; x = x <<16;}
-	if (x <= 0x00FFFFFFFFFFFFFF) {n = n + 8; x = x << 8;}
-	if (x <= 0x0FFFFFFFFFFFFFFF) {n = n + 4; x = x << 4;}
-	if (x <= 0x3FFFFFFFFFFFFFFF) {n = n + 2; x = x << 2;}
-	if (x <= 0x7FFFFFFFFFFFFFFF) {n = n + 1;}
+    n = 0;
+    if (x <= 0x00000000FFFFFFFF) {n = n +32; x = x <<32;}
+    if (x <= 0x0000FFFFFFFFFFFF) {n = n +16; x = x <<16;}
+    if (x <= 0x00FFFFFFFFFFFFFF) {n = n + 8; x = x << 8;}
+    if (x <= 0x0FFFFFFFFFFFFFFF) {n = n + 4; x = x << 4;}
+    if (x <= 0x3FFFFFFFFFFFFFFF) {n = n + 2; x = x << 2;}
+    if (x <= 0x7FFFFFFFFFFFFFFF) {n = n + 1;}
 
-	return n;
+    return n;
 }
 
 static inline void
 _mpd_div_words(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t u1, mpd_uint_t u0,
                mpd_uint_t v)
 {
-	const mpd_uint_t b = 4294967296;
-	mpd_uint_t un1, un0,
-	           vn1, vn0,
-	           q1, q0,
-	           un32, un21, un10,
-	           rhat, t;
-	int s;
-
-	assert(u1 < v);
-
-	s = nlz(v);
-	v = v << s;
-	vn1 = v >> 32;
-	vn0 = v & 0xFFFFFFFF;
-
-	t = (s == 0) ? 0 : u0 >> (64 - s);
-	un32 = (u1 << s) | t;
-	un10 = u0 << s;
-
-	un1 = un10 >> 32;
-	un0 = un10 & 0xFFFFFFFF;
-
-	q1 = un32 / vn1;
-	rhat = un32 - q1*vn1;
+    const mpd_uint_t b = 4294967296;
+    mpd_uint_t un1, un0,
+               vn1, vn0,
+               q1, q0,
+               un32, un21, un10,
+               rhat, t;
+    int s;
+
+    assert(u1 < v);
+
+    s = nlz(v);
+    v = v << s;
+    vn1 = v >> 32;
+    vn0 = v & 0xFFFFFFFF;
+
+    t = (s == 0) ? 0 : u0 >> (64 - s);
+    un32 = (u1 << s) | t;
+    un10 = u0 << s;
+
+    un1 = un10 >> 32;
+    un0 = un10 & 0xFFFFFFFF;
+
+    q1 = un32 / vn1;
+    rhat = un32 - q1*vn1;
 again1:
-	if (q1 >= b || q1*vn0 > b*rhat + un1) {
-		q1 = q1 - 1;
-		rhat = rhat + vn1;
-		if (rhat < b) goto again1;
-	}
-
-	/*
-	 *  Before again1 we had:
-	 *      (1) q1*vn1   + rhat         = un32
-	 *      (2) q1*vn1*b + rhat*b + un1 = un32*b + un1
-	 *
-	 *  The statements inside the if-clause do not change the value
-	 *  of the left-hand side of (2), and the loop is only exited
-	 *  if q1*vn0 <= rhat*b + un1, so:
-	 *
-	 *      (3) q1*vn1*b + q1*vn0 <= un32*b + un1
-	 *      (4)              q1*v <= un32*b + un1
-	 *      (5)                 0 <= un32*b + un1 - q1*v
-	 *
-	 *  By (5) we are certain that the possible add-back step from
-	 *  Knuth's algorithm D is never required.
-	 *
-	 *  Since the final quotient is less than 2**64, the following
-	 *  must be true:
-	 *
-	 *      (6) un32*b + un1 - q1*v <= UINT64_MAX
-	 *
-	 *  This means that in the following line, the high words
-	 *  of un32*b and q1*v can be discarded without any effect
-	 *  on the result.
-	 */
-	un21 = un32*b + un1 - q1*v;
-
-	q0 = un21 / vn1;
-	rhat = un21 - q0*vn1;
+    if (q1 >= b || q1*vn0 > b*rhat + un1) {
+        q1 = q1 - 1;
+        rhat = rhat + vn1;
+        if (rhat < b) goto again1;
+    }
+
+    /*
+     *  Before again1 we had:
+     *      (1) q1*vn1   + rhat         = un32
+     *      (2) q1*vn1*b + rhat*b + un1 = un32*b + un1
+     *
+     *  The statements inside the if-clause do not change the value
+     *  of the left-hand side of (2), and the loop is only exited
+     *  if q1*vn0 <= rhat*b + un1, so:
+     *
+     *      (3) q1*vn1*b + q1*vn0 <= un32*b + un1
+     *      (4)              q1*v <= un32*b + un1
+     *      (5)                 0 <= un32*b + un1 - q1*v
+     *
+     *  By (5) we are certain that the possible add-back step from
+     *  Knuth's algorithm D is never required.
+     *
+     *  Since the final quotient is less than 2**64, the following
+     *  must be true:
+     *
+     *      (6) un32*b + un1 - q1*v <= UINT64_MAX
+     *
+     *  This means that in the following line, the high words
+     *  of un32*b and q1*v can be discarded without any effect
+     *  on the result.
+     */
+    un21 = un32*b + un1 - q1*v;
+
+    q0 = un21 / vn1;
+    rhat = un21 - q0*vn1;
 again2:
-	if (q0 >= b || q0*vn0 > b*rhat + un0) {
-		q0 = q0 - 1;
-		rhat = rhat + vn1;
-		if (rhat < b) goto again2;
-	}
-
-	*q = q1*b + q0;
-	*r = (un21*b + un0 - q0*v) >> s;
+    if (q0 >= b || q0*vn0 > b*rhat + un0) {
+        q0 = q0 - 1;
+        rhat = rhat + vn1;
+        if (rhat < b) goto again2;
+    }
+
+    *q = q1*b + q0;
+    *r = (un21*b + un0 - q0*v) >> s;
 }
 #endif
 
@@ -205,32 +205,32 @@ again2:
 static inline void
 _mpd_mul_words(mpd_uint_t *hi, mpd_uint_t *lo, mpd_uint_t a, mpd_uint_t b)
 {
-	mpd_uint_t h, l;
+    mpd_uint_t h, l;
 
-	asm (	"mulq %3\n\t"
-		: "=d" (h), "=a" (l)
-		: "%a" (a), "rm" (b)
-		: "cc"
-	);
+    __asm__ ( "mulq %3\n\t"
+              : "=d" (h), "=a" (l)
+              : "%a" (a), "rm" (b)
+              : "cc"
+    );
 
-	*hi = h;
-	*lo = l;
+    *hi = h;
+    *lo = l;
 }
 
 static inline void
 _mpd_div_words(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t hi, mpd_uint_t lo,
                mpd_uint_t d)
 {
-	mpd_uint_t qq, rr;
+    mpd_uint_t qq, rr;
 
-	asm (	"divq %4\n\t"
-		: "=a" (qq), "=d" (rr)
-		: "a" (lo), "d" (hi), "rm" (d)
-		: "cc"
-	);
+    __asm__ ( "divq %4\n\t"
+              : "=a" (qq), "=d" (rr)
+              : "a" (lo), "d" (hi), "rm" (d)
+              : "cc"
+    );
 
-	*q = qq;
-	*r = rr;
+    *q = qq;
+    *r = rr;
 }
 /* END GCC ASM */
 #elif defined(MASM)
@@ -240,7 +240,7 @@ _mpd_div_words(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t hi, mpd_uint_t lo,
 static inline void
 _mpd_mul_words(mpd_uint_t *hi, mpd_uint_t *lo, mpd_uint_t a, mpd_uint_t b)
 {
-	*lo = _umul128(a, b, hi);
+    *lo = _umul128(a, b, hi);
 }
 
 void _mpd_div_words(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t hi, mpd_uint_t lo,
@@ -251,51 +251,52 @@ void _mpd_div_words(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t hi, mpd_uint_t lo,
   #error "need platform specific 128 bit multiplication and division"
 #endif
 
+#define DIVMOD(q, r, v, d) *q = v / d; *r = v - *q * d
 static inline void
 _mpd_divmod_pow10(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t v, mpd_uint_t exp)
 {
-  assert(exp <= 19);
-
-  if (exp <= 9) {
-    if (exp <= 4) {
-      switch (exp) {
-      case 0: *q = v; *r = 0; break;
-      case 1: *q = v / 10ULL; *r = v - *q * 10ULL; break;
-      case 2: *q = v / 100ULL; *r = v - *q * 100ULL; break;
-      case 3: *q = v / 1000ULL; *r = v - *q * 1000ULL; break;
-      case 4: *q = v / 10000ULL; *r = v - *q * 10000ULL; break;
-      }
-    }
-    else {
-      switch (exp) {
-      case 5: *q = v / 100000ULL; *r = v - *q * 100000ULL; break;
-      case 6: *q = v / 1000000ULL; *r = v - *q * 1000000ULL; break;
-      case 7: *q = v / 10000000ULL; *r = v - *q * 10000000ULL; break;
-      case 8: *q = v / 100000000ULL; *r = v - *q * 100000000ULL; break;
-      case 9: *q = v / 1000000000ULL; *r = v - *q * 1000000000ULL; break;
-      }
-    }
-  }
-  else {
-    if (exp <= 14) {
-      switch (exp) {
-      case 10: *q = v / 10000000000ULL; *r = v - *q * 10000000000ULL; break;
-      case 11: *q = v / 100000000000ULL; *r = v - *q * 100000000000ULL; break;
-      case 12: *q = v / 1000000000000ULL; *r = v - *q * 1000000000000ULL; break;
-      case 13: *q = v / 10000000000000ULL; *r = v - *q * 10000000000000ULL; break;
-      case 14: *q = v / 100000000000000ULL; *r = v - *q * 100000000000000ULL; break;
-      }
+    assert(exp <= 19);
+
+    if (exp <= 9) {
+        if (exp <= 4) {
+            switch (exp) {
+            case 0: *q = v; *r = 0; break;
+            case 1: DIVMOD(q, r, v, 10UL); break;
+            case 2: DIVMOD(q, r, v, 100UL); break;
+            case 3: DIVMOD(q, r, v, 1000UL); break;
+            case 4: DIVMOD(q, r, v, 10000UL); break;
+            }
+        }
+        else {
+            switch (exp) {
+            case 5: DIVMOD(q, r, v, 100000UL); break;
+            case 6: DIVMOD(q, r, v, 1000000UL); break;
+            case 7: DIVMOD(q, r, v, 10000000UL); break;
+            case 8: DIVMOD(q, r, v, 100000000UL); break;
+            case 9: DIVMOD(q, r, v, 1000000000UL); break;
+            }
+        }
     }
     else {
-      switch (exp) {
-      case 15: *q = v / 1000000000000000ULL; *r = v - *q * 1000000000000000ULL; break;
-      case 16: *q = v / 10000000000000000ULL; *r = v - *q * 10000000000000000ULL; break;
-      case 17: *q = v / 100000000000000000ULL; *r = v - *q * 100000000000000000ULL; break;
-      case 18: *q = v / 1000000000000000000ULL; *r = v - *q * 1000000000000000000ULL; break;
-      case 19: *q = v / 10000000000000000000ULL; *r = v - *q * 10000000000000000000ULL; break; /* GCOV_NOT_REACHED */
-      }
+        if (exp <= 14) {
+            switch (exp) {
+            case 10: DIVMOD(q, r, v, 10000000000ULL); break;
+            case 11: DIVMOD(q, r, v, 100000000000ULL); break;
+            case 12: DIVMOD(q, r, v, 1000000000000ULL); break;
+            case 13: DIVMOD(q, r, v, 10000000000000ULL); break;
+            case 14: DIVMOD(q, r, v, 100000000000000ULL); break;
+            }
+        }
+        else {
+            switch (exp) {
+            case 15: DIVMOD(q, r, v, 1000000000000000ULL); break;
+            case 16: DIVMOD(q, r, v, 10000000000000000ULL); break;
+            case 17: DIVMOD(q, r, v, 100000000000000000ULL); break;
+            case 18: DIVMOD(q, r, v, 1000000000000000000ULL); break;
+            case 19: DIVMOD(q, r, v, 10000000000000000000ULL); break; /* GCOV_NOT_REACHED */
+            }
+        }
     }
-  }
 }
 
 /* END CONFIG_64 */
@@ -305,54 +306,54 @@ _mpd_divmod_pow10(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t v, mpd_uint_t exp)
 static inline void
 _mpd_mul_words(mpd_uint_t *hi, mpd_uint_t *lo, mpd_uint_t a, mpd_uint_t b)
 {
-	mpd_uuint_t hl;
+    mpd_uuint_t hl;
 
-	hl = (mpd_uuint_t)a * b;
+    hl = (mpd_uuint_t)a * b;
 
-	*hi = hl >> 32;
-	*lo = (mpd_uint_t)hl;
+    *hi = hl >> 32;
+    *lo = (mpd_uint_t)hl;
 }
 
 static inline void
 _mpd_div_words(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t hi, mpd_uint_t lo,
                mpd_uint_t d)
 {
-	mpd_uuint_t hl;
+    mpd_uuint_t hl;
 
-	hl = ((mpd_uuint_t)hi<<32) + lo;
-	*q = (mpd_uint_t)(hl / d); /* quotient is known to fit */
-	*r = (mpd_uint_t)(hl - (mpd_uuint_t)(*q) * d);
+    hl = ((mpd_uuint_t)hi<<32) + lo;
+    *q = (mpd_uint_t)(hl / d); /* quotient is known to fit */
+    *r = (mpd_uint_t)(hl - (mpd_uuint_t)(*q) * d);
 }
 /* END ANSI + uint64_t */
 #else
 static inline void
 _mpd_mul_words(mpd_uint_t *hi, mpd_uint_t *lo, mpd_uint_t a, mpd_uint_t b)
 {
-	uint16_t w[4], carry;
-	uint16_t ah, al, bh, bl;
-	uint32_t hl;
+    uint16_t w[4], carry;
+    uint16_t ah, al, bh, bl;
+    uint32_t hl;
 
-	ah = (uint16_t)(a>>16); al = (uint16_t)a;
-	bh = (uint16_t)(b>>16); bl = (uint16_t)b;
+    ah = (uint16_t)(a>>16); al = (uint16_t)a;
+    bh = (uint16_t)(b>>16); bl = (uint16_t)b;
 
-	hl = (uint32_t)al * bl;
-	w[0] = (uint16_t)hl;
-	carry = (uint16_t)(hl>>16);
+    hl = (uint32_t)al * bl;
+    w[0] = (uint16_t)hl;
+    carry = (uint16_t)(hl>>16);
 
-	hl = (uint32_t)ah * bl + carry;
-	w[1] = (uint16_t)hl;
-	w[2] = (uint16_t)(hl>>16);
+    hl = (uint32_t)ah * bl + carry;
+    w[1] = (uint16_t)hl;
+    w[2] = (uint16_t)(hl>>16);
 
-	hl = (uint32_t)al * bh + w[1];
-	w[1] = (uint16_t)hl;
-	carry = (uint16_t)(hl>>16);
+    hl = (uint32_t)al * bh + w[1];
+    w[1] = (uint16_t)hl;
+    carry = (uint16_t)(hl>>16);
 
-	hl = ((uint32_t)ah * bh + w[2]) + carry;
-	w[2] = (uint16_t)hl;
-	w[3] = (uint16_t)(hl>>16);
+    hl = ((uint32_t)ah * bh + w[2]) + carry;
+    w[2] = (uint16_t)hl;
+    w[3] = (uint16_t)(hl>>16);
 
-	*hi = ((uint32_t)w[3]<<16) + w[2];
-	*lo = ((uint32_t)w[1]<<16) + w[0];
+    *hi = ((uint32_t)w[3]<<16) + w[2];
+    *lo = ((uint32_t)w[1]<<16) + w[0];
 }
 
 /*
@@ -366,93 +367,93 @@ _mpd_mul_words(mpd_uint_t *hi, mpd_uint_t *lo, mpd_uint_t a, mpd_uint_t b)
 static inline int
 nlz(uint32_t x)
 {
-	int n;
+    int n;
 
-	if (x == 0) return(32);
+    if (x == 0) return(32);
 
-	n = 0;
-	if (x <= 0x0000FFFF) {n = n +16; x = x <<16;}
-	if (x <= 0x00FFFFFF) {n = n + 8; x = x << 8;}
-	if (x <= 0x0FFFFFFF) {n = n + 4; x = x << 4;}
-	if (x <= 0x3FFFFFFF) {n = n + 2; x = x << 2;}
-	if (x <= 0x7FFFFFFF) {n = n + 1;}
+    n = 0;
+    if (x <= 0x0000FFFF) {n = n +16; x = x <<16;}
+    if (x <= 0x00FFFFFF) {n = n + 8; x = x << 8;}
+    if (x <= 0x0FFFFFFF) {n = n + 4; x = x << 4;}
+    if (x <= 0x3FFFFFFF) {n = n + 2; x = x << 2;}
+    if (x <= 0x7FFFFFFF) {n = n + 1;}
 
-	return n;
+    return n;
 }
 
 static inline void
 _mpd_div_words(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t u1, mpd_uint_t u0,
                mpd_uint_t v)
 {
-	const mpd_uint_t b = 65536;
-	mpd_uint_t un1, un0,
-	           vn1, vn0,
-	           q1, q0,
-	           un32, un21, un10,
-	           rhat, t;
-	int s;
-
-	assert(u1 < v);
-
-	s = nlz(v);
-	v = v << s;
-	vn1 = v >> 16;
-	vn0 = v & 0xFFFF;
-
-	t = (s == 0) ? 0 : u0 >> (32 - s);
-	un32 = (u1 << s) | t;
-	un10 = u0 << s;
-
-	un1 = un10 >> 16;
-	un0 = un10 & 0xFFFF;
-
-	q1 = un32 / vn1;
-	rhat = un32 - q1*vn1;
+    const mpd_uint_t b = 65536;
+    mpd_uint_t un1, un0,
+               vn1, vn0,
+               q1, q0,
+               un32, un21, un10,
+               rhat, t;
+    int s;
+
+    assert(u1 < v);
+
+    s = nlz(v);
+    v = v << s;
+    vn1 = v >> 16;
+    vn0 = v & 0xFFFF;
+
+    t = (s == 0) ? 0 : u0 >> (32 - s);
+    un32 = (u1 << s) | t;
+    un10 = u0 << s;
+
+    un1 = un10 >> 16;
+    un0 = un10 & 0xFFFF;
+
+    q1 = un32 / vn1;
+    rhat = un32 - q1*vn1;
 again1:
-	if (q1 >= b || q1*vn0 > b*rhat + un1) {
-		q1 = q1 - 1;
-		rhat = rhat + vn1;
-		if (rhat < b) goto again1;
-	}
-
-	/*
-	 *  Before again1 we had:
-	 *      (1) q1*vn1   + rhat         = un32
-	 *      (2) q1*vn1*b + rhat*b + un1 = un32*b + un1
-	 *
-	 *  The statements inside the if-clause do not change the value
-	 *  of the left-hand side of (2), and the loop is only exited
-	 *  if q1*vn0 <= rhat*b + un1, so:
-	 *
-	 *      (3) q1*vn1*b + q1*vn0 <= un32*b + un1
-	 *      (4)              q1*v <= un32*b + un1
-	 *      (5)                 0 <= un32*b + un1 - q1*v
-	 *
-	 *  By (5) we are certain that the possible add-back step from
-	 *  Knuth's algorithm D is never required.
-	 *
-	 *  Since the final quotient is less than 2**32, the following
-	 *  must be true:
-	 *
-	 *      (6) un32*b + un1 - q1*v <= UINT32_MAX
-	 *
-	 *  This means that in the following line, the high words
-	 *  of un32*b and q1*v can be discarded without any effect
-	 *  on the result.
-	 */
-	un21 = un32*b + un1 - q1*v;
-
-	q0 = un21 / vn1;
-	rhat = un21 - q0*vn1;
+    if (q1 >= b || q1*vn0 > b*rhat + un1) {
+        q1 = q1 - 1;
+        rhat = rhat + vn1;
+        if (rhat < b) goto again1;
+    }
+
+    /*
+     *  Before again1 we had:
+     *      (1) q1*vn1   + rhat         = un32
+     *      (2) q1*vn1*b + rhat*b + un1 = un32*b + un1
+     *
+     *  The statements inside the if-clause do not change the value
+     *  of the left-hand side of (2), and the loop is only exited
+     *  if q1*vn0 <= rhat*b + un1, so:
+     *
+     *      (3) q1*vn1*b + q1*vn0 <= un32*b + un1
+     *      (4)              q1*v <= un32*b + un1
+     *      (5)                 0 <= un32*b + un1 - q1*v
+     *
+     *  By (5) we are certain that the possible add-back step from
+     *  Knuth's algorithm D is never required.
+     *
+     *  Since the final quotient is less than 2**32, the following
+     *  must be true:
+     *
+     *      (6) un32*b + un1 - q1*v <= UINT32_MAX
+     *
+     *  This means that in the following line, the high words
+     *  of un32*b and q1*v can be discarded without any effect
+     *  on the result.
+     */
+    un21 = un32*b + un1 - q1*v;
+
+    q0 = un21 / vn1;
+    rhat = un21 - q0*vn1;
 again2:
-	if (q0 >= b || q0*vn0 > b*rhat + un0) {
-		q0 = q0 - 1;
-		rhat = rhat + vn1;
-		if (rhat < b) goto again2;
-	}
-
-	*q = q1*b + q0;
-	*r = (un21*b + un0 - q0*v) >> s;
+    if (q0 >= b || q0*vn0 > b*rhat + un0) {
+        q0 = q0 - 1;
+        rhat = rhat + vn1;
+        if (rhat < b) goto again2;
+    }
+
+    *q = q1*b + q0;
+    *r = (un21*b + un0 - q0*v) >> s;
 }
 #endif /* END ANSI + LEGACY_COMPILER */
 
@@ -461,96 +462,97 @@ again2:
 static inline void
 _mpd_mul_words(mpd_uint_t *hi, mpd_uint_t *lo, mpd_uint_t a, mpd_uint_t b)
 {
-	mpd_uint_t h, l;
+    mpd_uint_t h, l;
 
-	asm (	"mull %3\n\t"
-		: "=d" (h), "=a" (l)
-		: "%a" (a), "rm" (b)
-		: "cc"
-	);
+    __asm__ ( "mull %3\n\t"
+              : "=d" (h), "=a" (l)
+              : "%a" (a), "rm" (b)
+              : "cc"
+    );
 
-	*hi = h;
-	*lo = l;
+    *hi = h;
+    *lo = l;
 }
 
 static inline void
 _mpd_div_words(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t hi, mpd_uint_t lo,
                mpd_uint_t d)
 {
-	mpd_uint_t qq, rr;
+    mpd_uint_t qq, rr;
 
-	asm (	"divl %4\n\t"
-		: "=a" (qq), "=d" (rr)
-		: "a" (lo), "d" (hi), "rm" (d)
-		: "cc"
-	);
+    __asm__ ( "divl %4\n\t"
+              : "=a" (qq), "=d" (rr)
+              : "a" (lo), "d" (hi), "rm" (d)
+              : "cc"
+    );
 
-	*q = qq;
-	*r = rr;
+    *q = qq;
+    *r = rr;
 }
 /* END GCC ASM */
 #elif defined(MASM)
 static inline void __cdecl
 _mpd_mul_words(mpd_uint_t *hi, mpd_uint_t *lo, mpd_uint_t a, mpd_uint_t b)
 {
-	mpd_uint_t h, l;
+    mpd_uint_t h, l;
 
-	__asm {
-		mov eax, a
-		mul b
-		mov h, edx
-		mov l, eax
-	}
+    __asm {
+        mov eax, a
+        mul b
+        mov h, edx
+        mov l, eax
+    }
 
-	*hi = h;
-	*lo = l;
+    *hi = h;
+    *lo = l;
 }
 
 static inline void __cdecl
 _mpd_div_words(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t hi, mpd_uint_t lo,
                mpd_uint_t d)
 {
-	mpd_uint_t qq, rr;
-
-	__asm {
-		mov eax, lo
-		mov edx, hi
-		div d
-		mov qq, eax
-		mov rr, edx
-	}
-
-	*q = qq;
-	*r = rr;
+    mpd_uint_t qq, rr;
+
+    __asm {
+        mov eax, lo
+        mov edx, hi
+        div d
+        mov qq, eax
+        mov rr, edx
+    }
+
+    *q = qq;
+    *r = rr;
 }
 /* END MASM (_MSC_VER) */
 #else
   #error "need platform specific 64 bit multiplication and division"
 #endif
 
+#define DIVMOD(q, r, v, d) *q = v / d; *r = v - *q * d
 static inline void
 _mpd_divmod_pow10(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t v, mpd_uint_t exp)
 {
-  assert(exp <= 9);
-
-  if (exp <= 4) {
-    switch (exp) {
-    case 0: *q = v; *r = 0; break;
-    case 1: *q = v / 10UL; *r = v - *q * 10UL; break;
-    case 2: *q = v / 100UL; *r = v - *q * 100UL; break;
-    case 3: *q = v / 1000UL; *r = v - *q * 1000UL; break;
-    case 4: *q = v / 10000UL; *r = v - *q * 10000UL; break;
+    assert(exp <= 9);
+
+    if (exp <= 4) {
+        switch (exp) {
+        case 0: *q = v; *r = 0; break;
+        case 1: DIVMOD(q, r, v, 10UL); break;
+        case 2: DIVMOD(q, r, v, 100UL); break;
+        case 3: DIVMOD(q, r, v, 1000UL); break;
+        case 4: DIVMOD(q, r, v, 10000UL); break;
+        }
     }
-  }
-  else {
-    switch (exp) {
-    case 5: *q = v / 100000UL; *r = v - *q * 100000UL; break;
-    case 6: *q = v / 1000000UL; *r = v - *q * 1000000UL; break;
-    case 7: *q = v / 10000000UL; *r = v - *q * 10000000UL; break;
-    case 8: *q = v / 100000000UL; *r = v - *q * 100000000UL; break;
-    case 9: *q = v / 1000000000UL; *r = v - *q * 1000000000UL; break; /* GCOV_NOT_REACHED */
+    else {
+        switch (exp) {
+        case 5: DIVMOD(q, r, v, 100000UL); break;
+        case 6: DIVMOD(q, r, v, 1000000UL); break;
+        case 7: DIVMOD(q, r, v, 10000000UL); break;
+        case 8: DIVMOD(q, r, v, 100000000UL); break;
+        case 9: DIVMOD(q, r, v, 1000000000UL); break; /* GCOV_NOT_REACHED */
+        }
     }
-  }
 }
 /* END CONFIG_32 */
 
@@ -563,15 +565,15 @@ _mpd_divmod_pow10(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t v, mpd_uint_t exp)
 static inline void
 _mpd_div_word(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t v, mpd_uint_t d)
 {
-	*q = v / d;
-	*r = v - *q * d;
+    *q = v / d;
+    *r = v - *q * d;
 }
 
 static inline void
 _mpd_idiv_word(mpd_ssize_t *q, mpd_ssize_t *r, mpd_ssize_t v, mpd_ssize_t d)
 {
-	*q = v / d;
-	*r = v - *q * d;
+    *q = v / d;
+    *r = v - *q * d;
 }
 
 
@@ -579,22 +581,29 @@ _mpd_idiv_word(mpd_ssize_t *q, mpd_ssize_t *r, mpd_ssize_t v, mpd_ssize_t d)
  **              Arithmetic with overflow checking
  ** ------------------------------------------------------------
  */
+
+/* The following macros do call exit() in case of an overflow.
+   If the library is used correctly (i.e. with valid context
+   parameters), such overflows cannot occur. The macros are used
+   as sanity checks in a couple of strategic places and should
+   be viewed as a handwritten version of gcc's -ftrapv option. */
+
 static inline mpd_size_t
 add_size_t(mpd_size_t a, mpd_size_t b)
 {
-	if (a > MPD_SIZE_MAX - b) {
-		mpd_err_fatal("add_size_t(): overflow: check the context"); /* GCOV_NOT_REACHED */
-	}
-	return a + b;
+    if (a > MPD_SIZE_MAX - b) {
+        mpd_err_fatal("add_size_t(): overflow: check the context"); /* GCOV_NOT_REACHED */
+    }
+    return a + b;
 }
 
 static inline mpd_size_t
 sub_size_t(mpd_size_t a, mpd_size_t b)
 {
-	if (b > a) {
-		mpd_err_fatal("sub_size_t(): overflow: check the context"); /* GCOV_NOT_REACHED */
-	}
-	return a - b;
+    if (b > a) {
+        mpd_err_fatal("sub_size_t(): overflow: check the context"); /* GCOV_NOT_REACHED */
+    }
+    return a - b;
 }
 
 #if MPD_SIZE_MAX != MPD_UINT_MAX
@@ -604,32 +613,53 @@ sub_size_t(mpd_size_t a, mpd_size_t b)
 static inline mpd_size_t
 mul_size_t(mpd_size_t a, mpd_size_t b)
 {
-	mpd_uint_t hi, lo;
+    mpd_uint_t hi, lo;
+
+    _mpd_mul_words(&hi, &lo, (mpd_uint_t)a, (mpd_uint_t)b);
+    if (hi) {
+        mpd_err_fatal("mul_size_t(): overflow: check the context"); /* GCOV_NOT_REACHED */
+    }
+    return lo;
+}
+
+static inline mpd_size_t
+add_size_t_overflow(mpd_size_t a, mpd_size_t b, mpd_size_t *overflow)
+{
+    mpd_size_t ret;
+
+    *overflow = 0;
+    ret = a + b;
+    if (ret < a) *overflow = 1;
+    return ret;
+}
+
+static inline mpd_size_t
+mul_size_t_overflow(mpd_size_t a, mpd_size_t b, mpd_size_t *overflow)
+{
+    mpd_uint_t lo;
 
-	_mpd_mul_words(&hi, &lo, (mpd_uint_t)a, (mpd_uint_t)b);
-	if (hi) {
-		mpd_err_fatal("mul_size_t(): overflow: check the context"); /* GCOV_NOT_REACHED */
-	}
-	return lo;
+    _mpd_mul_words((mpd_uint_t *)overflow, &lo, (mpd_uint_t)a,
+                   (mpd_uint_t)b);
+    return lo;
 }
 
 static inline mpd_ssize_t
 mod_mpd_ssize_t(mpd_ssize_t a, mpd_ssize_t m)
 {
-	mpd_ssize_t r = a % m;
-	return (r < 0) ? r + m : r;
+    mpd_ssize_t r = a % m;
+    return (r < 0) ? r + m : r;
 }
 
 static inline mpd_size_t
 mulmod_size_t(mpd_size_t a, mpd_size_t b, mpd_size_t m)
 {
-	mpd_uint_t hi, lo;
-	mpd_uint_t q, r;
+    mpd_uint_t hi, lo;
+    mpd_uint_t q, r;
 
-	_mpd_mul_words(&hi, &lo, (mpd_uint_t)a, (mpd_uint_t)b);
-	_mpd_div_words(&q, &r, hi, lo, (mpd_uint_t)m);
+    _mpd_mul_words(&hi, &lo, (mpd_uint_t)a, (mpd_uint_t)b);
+    _mpd_div_words(&q, &r, hi, lo, (mpd_uint_t)m);
 
-	return r;
+    return r;
 }
 
 

+ 376 - 328
mpdecimal/umodarith.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2010 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -35,8 +35,12 @@
 #include "typearith.h"
 
 
+/* Bignum: Low level routines for unsigned modular arithmetic. These are
+   used in the fast convolution functions for very large coefficients. */
+
+
 /**************************************************************************/
-/*                      ANSI C99 modular arithmetic                       */
+/*                        ANSI modular arithmetic                         */
 /**************************************************************************/
 
 
@@ -47,13 +51,13 @@
 static inline mpd_uint_t
 addmod(mpd_uint_t a, mpd_uint_t b, mpd_uint_t m)
 {
-	mpd_uint_t s;
+    mpd_uint_t s;
 
-	s = a + b;
-	s = (s < a) ? s - m : s;
-	s = (s >= m) ? s - m : s;
+    s = a + b;
+    s = (s < a) ? s - m : s;
+    s = (s >= m) ? s - m : s;
 
-	return s;
+    return s;
 }
 
 /*
@@ -63,55 +67,63 @@ addmod(mpd_uint_t a, mpd_uint_t b, mpd_uint_t m)
 static inline mpd_uint_t
 submod(mpd_uint_t a, mpd_uint_t b, mpd_uint_t m)
 {
-	mpd_uint_t d;
+    mpd_uint_t d;
 
-	d = a - b;
-	d = (a < b) ? d + m : d;
+    d = a - b;
+    d = (a < b) ? d + m : d;
 
-	return d;
+    return d;
 }
 
 /*
  * Restrictions: a < 2m and b < 2m
- * ACL2 proof: umodarith.lisp: ext-submod-2-correct
+ * ACL2 proof: umodarith.lisp: section ext-submod
  */
 static inline mpd_uint_t
 ext_submod(mpd_uint_t a, mpd_uint_t b, mpd_uint_t m)
 {
-	mpd_uint_t d;
+    mpd_uint_t d;
 
-	a = (a >= m) ? a - m : a;
-	b = (b >= m) ? b - m : b;
+    a = (a >= m) ? a - m : a;
+    b = (b >= m) ? b - m : b;
 
-	d = a - b;
-	d = (a < b) ? d + m : d;
+    d = a - b;
+    d = (a < b) ? d + m : d;
 
-	return d;
+    return d;
 }
 
-/* divide 2 words by v, return remainder */
+/*
+ * Reduce double word modulo m.
+ * Restrictions: m != 0
+ * ACL2 proof: umodarith.lisp: section dw-reduce
+ */
 static inline mpd_uint_t
-bigmod2(mpd_uint_t hi, mpd_uint_t lo, mpd_uint_t v)
+dw_reduce(mpd_uint_t hi, mpd_uint_t lo, mpd_uint_t m)
 {
-	mpd_uint_t r1, r2, w;
+    mpd_uint_t r1, r2, w;
 
-	_mpd_div_word(&w, &r1, hi, v);
-	_mpd_div_words(&w, &r2, r1, lo, v);
+    _mpd_div_word(&w, &r1, hi, m);
+    _mpd_div_words(&w, &r2, r1, lo, m);
 
-	return r2;
+    return r2;
 }
 
-/* subtract double word hi,lo from a */
+/*
+ * Subtract double word from a.
+ * Restrictions: a < m
+ * ACL2 proof: umodarith.lisp: section dw-submod
+ */
 static inline mpd_uint_t
 dw_submod(mpd_uint_t a, mpd_uint_t hi, mpd_uint_t lo, mpd_uint_t m)
 {
-	mpd_uint_t d, r;
+    mpd_uint_t d, r;
 
-	r = bigmod2(hi, lo, m);
-	d = a - r;
-	d = (a < r) ? d + m : d;
+    r = dw_reduce(hi, lo, m);
+    d = a - r;
+    d = (a < r) ? d + m : d;
 
-	return d;
+    return d;
 }
 
 #ifdef CONFIG_64
@@ -121,150 +133,158 @@ dw_submod(mpd_uint_t a, mpd_uint_t hi, mpd_uint_t lo, mpd_uint_t m)
 /**************************************************************************/
 
 /*
- * Description of the algorithm in apfloat.pdf, Chapter 7.1.1,
- * by Mikko Tommila:  http://www.apfloat.org/apfloat/2.41/
+ * A proof of the algorithm is in literature/mulmod-64.txt. An ACL2
+ * proof is in umodarith.lisp: section "Fast modular reduction".
  *
- * ACL2 proof: umodarith.lisp: section "Fast modular reduction"
+ * Algorithm: calculate (a * b) % p:
+ *
+ *   a) hi, lo <- a * b       # Calculate a * b.
+ *
+ *   b) hi, lo <-  R(hi, lo)  # Reduce modulo p.
+ *
+ *   c) Repeat step b) until 0 <= hi * 2**64 + lo < 2*p.
+ *
+ *   d) If the result is less than p, return lo. Otherwise return lo - p.
  */
 
 static inline mpd_uint_t
 x64_mulmod(mpd_uint_t a, mpd_uint_t b, mpd_uint_t m)
 {
-	mpd_uint_t hi, lo, x, y;
+    mpd_uint_t hi, lo, x, y;
 
 
-	_mpd_mul_words(&hi, &lo, a, b);
+    _mpd_mul_words(&hi, &lo, a, b);
 
-	if (m & (1ULL<<32)) { /* P1 */
+    if (m & (1ULL<<32)) { /* P1 */
 
-		/* first reduction */
-		x = y = hi;
-		hi >>= 32;
+        /* first reduction */
+        x = y = hi;
+        hi >>= 32;
 
-		x = lo - x;
-		if (x > lo) hi--;
+        x = lo - x;
+        if (x > lo) hi--;
 
-		y <<= 32;
-		lo = y + x;
-		if (lo < y) hi++;
+        y <<= 32;
+        lo = y + x;
+        if (lo < y) hi++;
 
-		/* second reduction */
-		x = y = hi;
-		hi >>= 32;
+        /* second reduction */
+        x = y = hi;
+        hi >>= 32;
 
-		x = lo - x;
-		if (x > lo) hi--;
+        x = lo - x;
+        if (x > lo) hi--;
 
-		y <<= 32;
-		lo = y + x;
-		if (lo < y) hi++;
+        y <<= 32;
+        lo = y + x;
+        if (lo < y) hi++;
 
-		return (hi || lo >= m ? lo - m : lo);
-	}
-	else if (m & (1ULL<<34)) { /* P2 */
+        return (hi || lo >= m ? lo - m : lo);
+    }
+    else if (m & (1ULL<<34)) { /* P2 */
 
-		/* first reduction */
-		x = y = hi;
-		hi >>= 30;
+        /* first reduction */
+        x = y = hi;
+        hi >>= 30;
 
-		x = lo - x;
-		if (x > lo) hi--;
+        x = lo - x;
+        if (x > lo) hi--;
 
-		y <<= 34;
-		lo = y + x;
-		if (lo < y) hi++;
+        y <<= 34;
+        lo = y + x;
+        if (lo < y) hi++;
 
-		/* second reduction */
-		x = y = hi;
-		hi >>= 30;
+        /* second reduction */
+        x = y = hi;
+        hi >>= 30;
 
-		x = lo - x;
-		if (x > lo) hi--;
+        x = lo - x;
+        if (x > lo) hi--;
 
-		y <<= 34;
-		lo = y + x;
-		if (lo < y) hi++;
+        y <<= 34;
+        lo = y + x;
+        if (lo < y) hi++;
 
-		/* third reduction */
-		x = y = hi;
-		hi >>= 30;
+        /* third reduction */
+        x = y = hi;
+        hi >>= 30;
 
-		x = lo - x;
-		if (x > lo) hi--;
+        x = lo - x;
+        if (x > lo) hi--;
 
-		y <<= 34;
-		lo = y + x;
-		if (lo < y) hi++;
+        y <<= 34;
+        lo = y + x;
+        if (lo < y) hi++;
 
-		return (hi || lo >= m ? lo - m : lo);
-	}
-	else { /* P3 */
+        return (hi || lo >= m ? lo - m : lo);
+    }
+    else { /* P3 */
 
-		/* first reduction */
-		x = y = hi;
-		hi >>= 24;
+        /* first reduction */
+        x = y = hi;
+        hi >>= 24;
 
-		x = lo - x;
-		if (x > lo) hi--;
+        x = lo - x;
+        if (x > lo) hi--;
 
-		y <<= 40;
-		lo = y + x;
-		if (lo < y) hi++;
+        y <<= 40;
+        lo = y + x;
+        if (lo < y) hi++;
 
-		/* second reduction */
-		x = y = hi;
-		hi >>= 24;
+        /* second reduction */
+        x = y = hi;
+        hi >>= 24;
 
-		x = lo - x;
-		if (x > lo) hi--;
+        x = lo - x;
+        if (x > lo) hi--;
 
-		y <<= 40;
-		lo = y + x;
-		if (lo < y) hi++;
+        y <<= 40;
+        lo = y + x;
+        if (lo < y) hi++;
 
-		/* third reduction */
-		x = y = hi;
-		hi >>= 24;
+        /* third reduction */
+        x = y = hi;
+        hi >>= 24;
 
-		x = lo - x;
-		if (x > lo) hi--;
+        x = lo - x;
+        if (x > lo) hi--;
 
-		y <<= 40;
-		lo = y + x;
-		if (lo < y) hi++;
+        y <<= 40;
+        lo = y + x;
+        if (lo < y) hi++;
 
-		return (hi || lo >= m ? lo - m : lo);
-	}
+        return (hi || lo >= m ? lo - m : lo);
+    }
 }
 
 static inline void
 x64_mulmod2c(mpd_uint_t *a, mpd_uint_t *b, mpd_uint_t w, mpd_uint_t m)
 {
-	*a = x64_mulmod(*a, w, m);
-	*b = x64_mulmod(*b, w, m);
+    *a = x64_mulmod(*a, w, m);
+    *b = x64_mulmod(*b, w, m);
 }
 
 static inline void
 x64_mulmod2(mpd_uint_t *a0, mpd_uint_t b0, mpd_uint_t *a1, mpd_uint_t b1,
             mpd_uint_t m)
 {
-	*a0 = x64_mulmod(*a0, b0, m);
-	*a1 = x64_mulmod(*a1, b1, m);
+    *a0 = x64_mulmod(*a0, b0, m);
+    *a1 = x64_mulmod(*a1, b1, m);
 }
 
 static inline mpd_uint_t
 x64_powmod(mpd_uint_t base, mpd_uint_t exp, mpd_uint_t umod)
 {
-	mpd_uint_t r = 1;
+    mpd_uint_t r = 1;
 
-	while (exp > 0) {
-		if (exp & 1)
-			r = x64_mulmod(r, base, umod);
-		base = x64_mulmod(base, base, umod);
-		exp >>= 1;
-	}
+    while (exp > 0) {
+        if (exp & 1)
+            r = x64_mulmod(r, base, umod);
+        base = x64_mulmod(base, base, umod);
+        exp >>= 1;
+    }
 
-	return r;
+    return r;
 }
 
 /* END CONFIG_64 */
@@ -281,22 +301,22 @@ x64_powmod(mpd_uint_t base, mpd_uint_t exp, mpd_uint_t umod)
 static inline mpd_uint_t
 std_mulmod(mpd_uint_t a, mpd_uint_t b, mpd_uint_t m)
 {
-	return ((mpd_uuint_t) a * b) % m;
+    return ((mpd_uuint_t) a * b) % m;
 }
 
 static inline void
 std_mulmod2c(mpd_uint_t *a, mpd_uint_t *b, mpd_uint_t w, mpd_uint_t m)
 {
-	*a = ((mpd_uuint_t) *a * w) % m;
-	*b = ((mpd_uuint_t) *b * w) % m;
+    *a = ((mpd_uuint_t) *a * w) % m;
+    *b = ((mpd_uuint_t) *b * w) % m;
 }
 
 static inline void
 std_mulmod2(mpd_uint_t *a0, mpd_uint_t b0, mpd_uint_t *a1, mpd_uint_t b1,
             mpd_uint_t m)
 {
-	*a0 = ((mpd_uuint_t) *a0 * b0) % m;
-	*a1 = ((mpd_uuint_t) *a1 * b1) % m;
+    *a0 = ((mpd_uuint_t) *a0 * b0) % m;
+    *a1 = ((mpd_uuint_t) *a1 * b1) % m;
 }
 /* END HAVE_UINT64_T */
 #else
@@ -304,25 +324,25 @@ std_mulmod2(mpd_uint_t *a0, mpd_uint_t b0, mpd_uint_t *a1, mpd_uint_t b1,
 static inline mpd_uint_t
 std_mulmod(mpd_uint_t a, mpd_uint_t b, mpd_uint_t m)
 {
-	mpd_uint_t hi, lo, q, r;
-	_mpd_mul_words(&hi, &lo, a, b);
-	_mpd_div_words(&q, &r, hi, lo, m);
-	return r;
+    mpd_uint_t hi, lo, q, r;
+    _mpd_mul_words(&hi, &lo, a, b);
+    _mpd_div_words(&q, &r, hi, lo, m);
+    return r;
 }
 
 static inline void
 std_mulmod2c(mpd_uint_t *a, mpd_uint_t *b, mpd_uint_t w, mpd_uint_t m)
 {
-	*a = std_mulmod(*a, w, m);
-	*b = std_mulmod(*b, w, m);
+    *a = std_mulmod(*a, w, m);
+    *b = std_mulmod(*b, w, m);
 }
 
 static inline void
 std_mulmod2(mpd_uint_t *a0, mpd_uint_t b0, mpd_uint_t *a1, mpd_uint_t b1,
             mpd_uint_t m)
 {
-	*a0 = std_mulmod(*a0, b0, m);
-	*a1 = std_mulmod(*a1, b1, m);
+    *a0 = std_mulmod(*a0, b0, m);
+    *a1 = std_mulmod(*a1, b1, m);
 }
 /* END LEGACY_COMPILER */
 #endif
@@ -330,16 +350,16 @@ std_mulmod2(mpd_uint_t *a0, mpd_uint_t b0, mpd_uint_t *a1, mpd_uint_t b1,
 static inline mpd_uint_t
 std_powmod(mpd_uint_t base, mpd_uint_t exp, mpd_uint_t umod)
 {
-	mpd_uint_t r = 1;
+    mpd_uint_t r = 1;
 
-	while (exp > 0) {
-		if (exp & 1)
-			r = std_mulmod(r, base, umod);
-		base = std_mulmod(base, base, umod);
-		exp >>= 1;
-	}
+    while (exp > 0) {
+        if (exp & 1)
+            r = std_mulmod(r, base, umod);
+        base = std_mulmod(base, base, umod);
+        exp >>= 1;
+    }
 
-	return r;
+    return r;
 }
 #endif /* ANSI CONFIG_32 */
 
@@ -349,13 +369,25 @@ std_powmod(mpd_uint_t base, mpd_uint_t exp, mpd_uint_t umod)
 /**************************************************************************/
 
 /*
- * Description of the algorithm in apfloat.pdf, Chapter 7.1.1, by Mikko Tommila.
- * http://www.apfloat.org/apfloat/2.41/
+ * A proof of the algorithm is in literature/mulmod-ppro.txt. The FPU
+ * control word must be set to 64-bit precision and truncation mode
+ * prior to using these functions.
+ *
+ * Algorithm: calculate (a * b) % p:
+ *
+ *   p    := prime < 2**31
+ *   pinv := (long double)1.0 / p (precalculated)
+ *
+ *   a) n = a * b              # Calculate exact product.
+ *   b) qest = n * pinv        # Calculate estimate for q = n / p.
+ *   c) q = (qest+2**63)-2**63 # Truncate qest to the exact quotient.
+ *   d) r = n - q * p          # Calculate remainder.
  *
  * Remarks:
  *
+ *   - p = dmod and pinv = dinvmod.
  *   - dinvmod points to an array of three uint32_t, which is interpreted
- *     as an 80 bit long double.
+ *     as an 80 bit long double by fldt.
  *   - Intel compilers prior to version 11 do not seem to handle the
  *     __GNUC__ inline assembly correctly.
  *   - random tests are provided in tests/extended/ppro_mulmod.c
@@ -364,233 +396,249 @@ std_powmod(mpd_uint_t base, mpd_uint_t exp, mpd_uint_t umod)
 #if defined(PPRO)
 #if defined(ASM)
 
-/* all operands < dmod */
+/* Return (a * b) % dmod */
 static inline mpd_uint_t
 ppro_mulmod(mpd_uint_t a, mpd_uint_t b, double *dmod, uint32_t *dinvmod)
 {
-	mpd_uint_t retval;
-
-	asm (
-		"fildl	%2\n\t"
-		"fildl	%1\n\t"
-		"fmulp	%%st, %%st(1)\n\t"
-		"fldt	(%4)\n\t"
-		"fmul	%%st(1), %%st\n\t"
-		"flds	%5\n\t"
-		"fadd	%%st, %%st(1)\n\t"
-		"fsubrp	%%st, %%st(1)\n\t"
-		"fldl	(%3)\n\t"
-		"fmulp	%%st, %%st(1)\n\t"
-		"fsubrp	%%st, %%st(1)\n\t"
-		"fistpl	%0\n\t"
-		: "=m" (retval)
-		: "m" (a), "m" (b), "r" (dmod), "r" (dinvmod), "m" (MPD_TWO63)
-		: "st", "memory"
-	);
-
-	return retval;
+    mpd_uint_t retval;
+
+    __asm__ (
+            "fildl  %2\n\t"
+            "fildl  %1\n\t"
+            "fmulp  %%st, %%st(1)\n\t"
+            "fldt   (%4)\n\t"
+            "fmul   %%st(1), %%st\n\t"
+            "flds   %5\n\t"
+            "fadd   %%st, %%st(1)\n\t"
+            "fsubrp %%st, %%st(1)\n\t"
+            "fldl   (%3)\n\t"
+            "fmulp  %%st, %%st(1)\n\t"
+            "fsubrp %%st, %%st(1)\n\t"
+            "fistpl %0\n\t"
+            : "=m" (retval)
+            : "m" (a), "m" (b), "r" (dmod), "r" (dinvmod), "m" (MPD_TWO63)
+            : "st", "memory"
+    );
+
+    return retval;
 }
 
-/* all operands < dmod */
+/*
+ * Two modular multiplications in parallel:
+ *      *a0 = (*a0 * w) % dmod
+ *      *a1 = (*a1 * w) % dmod
+ */
 static inline void
 ppro_mulmod2c(mpd_uint_t *a0, mpd_uint_t *a1, mpd_uint_t w,
               double *dmod, uint32_t *dinvmod)
 {
-	asm (
-		"fildl	%2\n\t"
-		"fildl	(%1)\n\t"
-		"fmul	%%st(1), %%st\n\t"
-		"fxch	%%st(1)\n\t"
-		"fildl	(%0)\n\t"
-		"fmulp	%%st, %%st(1) \n\t"
-		"fldt	(%4)\n\t"
-		"flds	%5\n\t"
-		"fld	%%st(2)\n\t"
-		"fmul	%%st(2)\n\t"
-		"fadd	%%st(1)\n\t"
-		"fsub	%%st(1)\n\t"
-		"fmull	(%3)\n\t"
-		"fsubrp %%st, %%st(3)\n\t"
-		"fxch   %%st(2)\n\t"
-		"fistpl	(%0)\n\t"
-		"fmul	%%st(2)\n\t"
-		"fadd	%%st(1)\n\t"
-		"fsubp  %%st, %%st(1)\n\t"
-		"fmull  (%3)\n\t"
-		"fsubrp %%st, %%st(1)\n\t"
-		"fistpl (%1)\n\t"
-		: : "r" (a0), "r" (a1), "m" (w),
-		    "r" (dmod), "r" (dinvmod),
-		    "m" (MPD_TWO63)
-		: "st", "memory"
-	);
+    __asm__ (
+            "fildl  %2\n\t"
+            "fildl  (%1)\n\t"
+            "fmul   %%st(1), %%st\n\t"
+            "fxch   %%st(1)\n\t"
+            "fildl  (%0)\n\t"
+            "fmulp  %%st, %%st(1) \n\t"
+            "fldt   (%4)\n\t"
+            "flds   %5\n\t"
+            "fld    %%st(2)\n\t"
+            "fmul   %%st(2)\n\t"
+            "fadd   %%st(1)\n\t"
+            "fsub   %%st(1)\n\t"
+            "fmull  (%3)\n\t"
+            "fsubrp %%st, %%st(3)\n\t"
+            "fxch   %%st(2)\n\t"
+            "fistpl (%0)\n\t"
+            "fmul   %%st(2)\n\t"
+            "fadd   %%st(1)\n\t"
+            "fsubp  %%st, %%st(1)\n\t"
+            "fmull  (%3)\n\t"
+            "fsubrp %%st, %%st(1)\n\t"
+            "fistpl (%1)\n\t"
+            : : "r" (a0), "r" (a1), "m" (w),
+                "r" (dmod), "r" (dinvmod),
+                "m" (MPD_TWO63)
+            : "st", "memory"
+    );
 }
 
-/* all operands < dmod */
+/*
+ * Two modular multiplications in parallel:
+ *      *a0 = (*a0 * b0) % dmod
+ *      *a1 = (*a1 * b1) % dmod
+ */
 static inline void
 ppro_mulmod2(mpd_uint_t *a0, mpd_uint_t b0, mpd_uint_t *a1, mpd_uint_t b1,
              double *dmod, uint32_t *dinvmod)
 {
-	asm (
-		"fildl	%3\n\t"
-		"fildl	(%2)\n\t"
-		"fmulp	%%st, %%st(1)\n\t"
-		"fildl	%1\n\t"
-		"fildl	(%0)\n\t"
-		"fmulp	%%st, %%st(1)\n\t"
-		"fldt	(%5)\n\t"
-		"fld	%%st(2)\n\t"
-		"fmul	%%st(1), %%st\n\t"
-		"fxch	%%st(1)\n\t"
-		"fmul	%%st(2), %%st\n\t"
-		"flds	%6\n\t"
-		"fldl	(%4)\n\t"
-		"fxch	%%st(3)\n\t"
-		"fadd	%%st(1), %%st\n\t"
-		"fxch	%%st(2)\n\t"
-		"fadd	%%st(1), %%st\n\t"
-		"fxch	%%st(2)\n\t"
-		"fsub	%%st(1), %%st\n\t"
-		"fxch	%%st(2)\n\t"
-		"fsubp	%%st, %%st(1)\n\t"
-		"fxch	%%st(1)\n\t"
-		"fmul	%%st(2), %%st\n\t"
-		"fxch	%%st(1)\n\t"
-		"fmulp	%%st, %%st(2)\n\t"
-		"fsubrp	%%st, %%st(3)\n\t"
-		"fsubrp	%%st, %%st(1)\n\t"
-		"fxch	%%st(1)\n\t"
-		"fistpl	(%2)\n\t"
-		"fistpl	(%0)\n\t"
-		: : "r" (a0), "m" (b0), "r" (a1), "m" (b1),
-		    "r" (dmod), "r" (dinvmod),
-		    "m" (MPD_TWO63)
-		: "st", "memory"
-	);
+    __asm__ (
+            "fildl  %3\n\t"
+            "fildl  (%2)\n\t"
+            "fmulp  %%st, %%st(1)\n\t"
+            "fildl  %1\n\t"
+            "fildl  (%0)\n\t"
+            "fmulp  %%st, %%st(1)\n\t"
+            "fldt   (%5)\n\t"
+            "fld    %%st(2)\n\t"
+            "fmul   %%st(1), %%st\n\t"
+            "fxch   %%st(1)\n\t"
+            "fmul   %%st(2), %%st\n\t"
+            "flds   %6\n\t"
+            "fldl   (%4)\n\t"
+            "fxch   %%st(3)\n\t"
+            "fadd   %%st(1), %%st\n\t"
+            "fxch   %%st(2)\n\t"
+            "fadd   %%st(1), %%st\n\t"
+            "fxch   %%st(2)\n\t"
+            "fsub   %%st(1), %%st\n\t"
+            "fxch   %%st(2)\n\t"
+            "fsubp  %%st, %%st(1)\n\t"
+            "fxch   %%st(1)\n\t"
+            "fmul   %%st(2), %%st\n\t"
+            "fxch   %%st(1)\n\t"
+            "fmulp  %%st, %%st(2)\n\t"
+            "fsubrp %%st, %%st(3)\n\t"
+            "fsubrp %%st, %%st(1)\n\t"
+            "fxch   %%st(1)\n\t"
+            "fistpl (%2)\n\t"
+            "fistpl (%0)\n\t"
+            : : "r" (a0), "m" (b0), "r" (a1), "m" (b1),
+                "r" (dmod), "r" (dinvmod),
+                "m" (MPD_TWO63)
+            : "st", "memory"
+    );
 }
 /* END PPRO GCC ASM */
 #elif defined(MASM)
 
-/* all operands < dmod */
+/* Return (a * b) % dmod */
 static inline mpd_uint_t __cdecl
 ppro_mulmod(mpd_uint_t a, mpd_uint_t b, double *dmod, uint32_t *dinvmod)
 {
-	mpd_uint_t retval;
-
-	__asm {
-		mov	eax, dinvmod
-		mov	edx, dmod
-		fild	b
-		fild	a
-		fmulp	st(1), st
-		fld	TBYTE PTR [eax]
-		fmul	st, st(1)
-		fld	MPD_TWO63
-		fadd	st(1), st
-		fsubp	st(1), st
-		fld	QWORD PTR [edx]
-		fmulp	st(1), st
-		fsubp	st(1), st
-		fistp	retval
-	}
-
-	return retval;
+    mpd_uint_t retval;
+
+    __asm {
+        mov     eax, dinvmod
+        mov     edx, dmod
+        fild    b
+        fild    a
+        fmulp   st(1), st
+        fld     TBYTE PTR [eax]
+        fmul    st, st(1)
+        fld     MPD_TWO63
+        fadd    st(1), st
+        fsubp   st(1), st
+        fld     QWORD PTR [edx]
+        fmulp   st(1), st
+        fsubp   st(1), st
+        fistp   retval
+    }
+
+    return retval;
 }
 
-/* all operands < dmod */
+/*
+ * Two modular multiplications in parallel:
+ *      *a0 = (*a0 * w) % dmod
+ *      *a1 = (*a1 * w) % dmod
+ */
 static inline mpd_uint_t __cdecl
 ppro_mulmod2c(mpd_uint_t *a0, mpd_uint_t *a1, mpd_uint_t w,
               double *dmod, uint32_t *dinvmod)
 {
-	__asm {
-		mov	ecx, dmod
-		mov	edx, a1
-		mov	ebx, dinvmod
-		mov	eax, a0
-		fild	w
-		fild	DWORD PTR [edx]
-		fmul	st, st(1)
-		fxch	st(1)
-		fild	DWORD PTR [eax]
-		fmulp	st(1), st
-		fld	TBYTE PTR [ebx]
-		fld	MPD_TWO63
-		fld	st(2)
-		fmul	st, st(2)
-		fadd	st, st(1)
-		fsub	st, st(1)
-		fmul	QWORD PTR [ecx]
-		fsubp	st(3), st
-		fxch	st(2)
-		fistp	DWORD PTR [eax]
-		fmul	st, st(2)
-		fadd	st, st(1)
-		fsubrp	st(1), st
-		fmul	QWORD PTR [ecx]
-		fsubp	st(1), st
-		fistp	DWORD PTR [edx]
-	}
+    __asm {
+        mov     ecx, dmod
+        mov     edx, a1
+        mov     ebx, dinvmod
+        mov     eax, a0
+        fild    w
+        fild    DWORD PTR [edx]
+        fmul    st, st(1)
+        fxch    st(1)
+        fild    DWORD PTR [eax]
+        fmulp   st(1), st
+        fld     TBYTE PTR [ebx]
+        fld     MPD_TWO63
+        fld     st(2)
+        fmul    st, st(2)
+        fadd    st, st(1)
+        fsub    st, st(1)
+        fmul    QWORD PTR [ecx]
+        fsubp   st(3), st
+        fxch    st(2)
+        fistp   DWORD PTR [eax]
+        fmul    st, st(2)
+        fadd    st, st(1)
+        fsubrp  st(1), st
+        fmul    QWORD PTR [ecx]
+        fsubp   st(1), st
+        fistp   DWORD PTR [edx]
+    }
 }
 
-/* all operands < dmod */
+/*
+ * Two modular multiplications in parallel:
+ *      *a0 = (*a0 * b0) % dmod
+ *      *a1 = (*a1 * b1) % dmod
+ */
 static inline void __cdecl
 ppro_mulmod2(mpd_uint_t *a0, mpd_uint_t b0, mpd_uint_t *a1, mpd_uint_t b1,
              double *dmod, uint32_t *dinvmod)
 {
-	__asm {
-		mov	ecx, dmod
-		mov	edx, a1
-		mov	ebx, dinvmod
-		mov	eax, a0
-		fild	b1
-		fild	DWORD PTR [edx]
-		fmulp	st(1), st
-		fild	b0
-		fild	DWORD PTR [eax]
-		fmulp	st(1), st
-		fld	TBYTE PTR [ebx]
-		fld	st(2)
-		fmul	st, st(1)
-		fxch	st(1)
-		fmul	st, st(2)
-		fld	DWORD PTR MPD_TWO63
-		fld	QWORD PTR [ecx]
-		fxch	st(3)
-		fadd	st, st(1)
-		fxch	st(2)
-		fadd	st, st(1)
-		fxch	st(2)
-		fsub	st, st(1)
-		fxch	st(2)
-		fsubrp	st(1), st
-		fxch	st(1)
-		fmul	st, st(2)
-		fxch	st(1)
-		fmulp	st(2), st
-		fsubp	st(3), st
-		fsubp	st(1), st
-		fxch	st(1)
-		fistp	DWORD PTR [edx]
-		fistp	DWORD PTR [eax]
-	}
+    __asm {
+        mov     ecx, dmod
+        mov     edx, a1
+        mov     ebx, dinvmod
+        mov     eax, a0
+        fild    b1
+        fild    DWORD PTR [edx]
+        fmulp   st(1), st
+        fild    b0
+        fild    DWORD PTR [eax]
+        fmulp   st(1), st
+        fld     TBYTE PTR [ebx]
+        fld     st(2)
+        fmul    st, st(1)
+        fxch    st(1)
+        fmul    st, st(2)
+        fld     DWORD PTR MPD_TWO63
+        fld     QWORD PTR [ecx]
+        fxch    st(3)
+        fadd    st, st(1)
+        fxch    st(2)
+        fadd    st, st(1)
+        fxch    st(2)
+        fsub    st, st(1)
+        fxch    st(2)
+        fsubrp  st(1), st
+        fxch    st(1)
+        fmul    st, st(2)
+        fxch    st(1)
+        fmulp   st(2), st
+        fsubp   st(3), st
+        fsubp   st(1), st
+        fxch    st(1)
+        fistp   DWORD PTR [edx]
+        fistp   DWORD PTR [eax]
+    }
 }
 #endif /* PPRO MASM (_MSC_VER) */
 
 
-/* all operands < dmod */
+/* Return (base ** exp) % dmod */
 static inline mpd_uint_t
 ppro_powmod(mpd_uint_t base, mpd_uint_t exp, double *dmod, uint32_t *dinvmod)
 {
-	mpd_uint_t r = 1;
+    mpd_uint_t r = 1;
 
-	while (exp > 0) {
-		if (exp & 1)
-			r = ppro_mulmod(r, base, dmod, dinvmod);
-		base = ppro_mulmod(base, base, dmod, dinvmod);
-		exp >>= 1;
-	}
+    while (exp > 0) {
+        if (exp & 1)
+            r = ppro_mulmod(r, base, dmod, dinvmod);
+        base = ppro_mulmod(base, base, dmod, dinvmod);
+        exp >>= 1;
+    }
 
-	return r;
+    return r;
 }
 #endif /* PPRO */
 #endif /* CONFIG_32 */

+ 62 - 0
mpdecimal/vccompat.h

@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#ifndef VCCOMPAT_H
+#define VCCOMPAT_H
+
+
+/* Visual C fixes: no stdint.h, no snprintf ... */
+#ifdef _MSC_VER
+  #include "vcstdint.h"
+  #undef inline
+  #define inline __inline
+  #undef random
+  #define random rand
+  #undef srandom
+  #define srandom srand
+  #undef snprintf
+  #define snprintf sprintf_s
+  #define HAVE_SNPRINTF
+  #undef strncasecmp
+  #define strncasecmp _strnicmp
+  #undef strcasecmp
+  #define strcasecmp _stricmp
+  #undef strtoll
+  #define strtoll _strtoi64
+  #define strdup _strdup
+  #define PRIi64 "I64i"
+  #define PRIu64 "I64u"
+  #define PRIi32 "I32i"
+  #define PRIu32 "I32u"
+#endif
+
+
+#endif /* VCCOMPAT_H */
+
+
+

+ 48 - 0
mpdecimal/vcdiv64.asm

@@ -0,0 +1,48 @@
+;
+; Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions
+; are met:
+;
+; 1. Redistributions of source code must retain the above copyright
+;    notice, this list of conditions and the following disclaimer.
+;
+; 2. Redistributions in binary form must reproduce the above copyright
+;    notice, this list of conditions and the following disclaimer in the
+;    documentation and/or other materials provided with the distribution.
+;
+; THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
+; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+; ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+; FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+; OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+; HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+; LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+; OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+; SUCH DAMAGE.
+;
+
+
+PUBLIC    _mpd_div_words
+_TEXT    SEGMENT
+q$ = 8
+r$ = 16
+hi$ = 24
+lo$ = 32
+d$ = 40
+_mpd_div_words PROC
+    mov    r10, rdx
+    mov    rdx, r8
+    mov    rax, r9
+    div    QWORD PTR d$[rsp]
+    mov    QWORD PTR [r10], rdx
+    mov    QWORD PTR [rcx], rax
+    ret    0
+_mpd_div_words ENDP
+_TEXT    ENDS
+END
+
+

+ 232 - 0
mpdecimal/vcstdint.h

@@ -0,0 +1,232 @@
+// ISO C9x  compliant stdint.h for Microsoft Visual Studio
+// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
+//
+//  Copyright (c) 2006-2008 Alexander Chemeris
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   1. Redistributions of source code must retain the above copyright notice,
+//      this list of conditions and the following disclaimer.
+//
+//   2. Redistributions in binary form must reproduce the above copyright
+//      notice, this list of conditions and the following disclaimer in the
+//      documentation and/or other materials provided with the distribution.
+//
+//   3. The name of the author may be used to endorse or promote products
+//      derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _MSC_VER // [
+#error "Use this header only with Microsoft Visual C++ compilers!"
+#endif // _MSC_VER ]
+
+#ifndef _MSC_STDINT_H_ // [
+#define _MSC_STDINT_H_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif
+
+#include <limits.h>
+
+// For Visual Studio 6 in C++ mode wrap <wchar.h> include with 'extern "C++" {}'
+// or compiler give many errors like this:
+//   error C2733: second C linkage of overloaded function 'wmemchr' not allowed
+#if (_MSC_VER < 1300) && defined(__cplusplus)
+   extern "C++" {
+#endif
+#     include <wchar.h>
+#if (_MSC_VER < 1300) && defined(__cplusplus)
+   }
+#endif
+
+// Define _W64 macros to mark types changing their size, like intptr_t.
+#ifndef _W64
+#  if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
+#     define _W64 __w64
+#  else
+#     define _W64
+#  endif
+#endif
+
+
+// 7.18.1 Integer types
+
+// 7.18.1.1 Exact-width integer types
+typedef __int8            int8_t;
+typedef __int16           int16_t;
+typedef __int32           int32_t;
+typedef __int64           int64_t;
+typedef unsigned __int8   uint8_t;
+typedef unsigned __int16  uint16_t;
+typedef unsigned __int32  uint32_t;
+typedef unsigned __int64  uint64_t;
+
+// 7.18.1.2 Minimum-width integer types
+typedef int8_t    int_least8_t;
+typedef int16_t   int_least16_t;
+typedef int32_t   int_least32_t;
+typedef int64_t   int_least64_t;
+typedef uint8_t   uint_least8_t;
+typedef uint16_t  uint_least16_t;
+typedef uint32_t  uint_least32_t;
+typedef uint64_t  uint_least64_t;
+
+// 7.18.1.3 Fastest minimum-width integer types
+typedef int8_t    int_fast8_t;
+typedef int16_t   int_fast16_t;
+typedef int32_t   int_fast32_t;
+typedef int64_t   int_fast64_t;
+typedef uint8_t   uint_fast8_t;
+typedef uint16_t  uint_fast16_t;
+typedef uint32_t  uint_fast32_t;
+typedef uint64_t  uint_fast64_t;
+
+// 7.18.1.4 Integer types capable of holding object pointers
+#ifdef _WIN64 // [
+   typedef __int64           intptr_t;
+   typedef unsigned __int64  uintptr_t;
+#else // _WIN64 ][
+   typedef _W64 int               intptr_t;
+   typedef _W64 unsigned int      uintptr_t;
+#endif // _WIN64 ]
+
+// 7.18.1.5 Greatest-width integer types
+typedef int64_t   intmax_t;
+typedef uint64_t  uintmax_t;
+
+
+// 7.18.2 Limits of specified-width integer types
+
+#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [   See footnote 220 at page 257 and footnote 221 at page 259
+
+// 7.18.2.1 Limits of exact-width integer types
+#define INT8_MIN     ((int8_t)_I8_MIN)
+#define INT8_MAX     _I8_MAX
+#define INT16_MIN    ((int16_t)_I16_MIN)
+#define INT16_MAX    _I16_MAX
+#define INT32_MIN    ((int32_t)_I32_MIN)
+#define INT32_MAX    _I32_MAX
+#define INT64_MIN    ((int64_t)_I64_MIN)
+#define INT64_MAX    _I64_MAX
+#define UINT8_MAX    _UI8_MAX
+#define UINT16_MAX   _UI16_MAX
+#define UINT32_MAX   _UI32_MAX
+#define UINT64_MAX   _UI64_MAX
+
+// 7.18.2.2 Limits of minimum-width integer types
+#define INT_LEAST8_MIN    INT8_MIN
+#define INT_LEAST8_MAX    INT8_MAX
+#define INT_LEAST16_MIN   INT16_MIN
+#define INT_LEAST16_MAX   INT16_MAX
+#define INT_LEAST32_MIN   INT32_MIN
+#define INT_LEAST32_MAX   INT32_MAX
+#define INT_LEAST64_MIN   INT64_MIN
+#define INT_LEAST64_MAX   INT64_MAX
+#define UINT_LEAST8_MAX   UINT8_MAX
+#define UINT_LEAST16_MAX  UINT16_MAX
+#define UINT_LEAST32_MAX  UINT32_MAX
+#define UINT_LEAST64_MAX  UINT64_MAX
+
+// 7.18.2.3 Limits of fastest minimum-width integer types
+#define INT_FAST8_MIN    INT8_MIN
+#define INT_FAST8_MAX    INT8_MAX
+#define INT_FAST16_MIN   INT16_MIN
+#define INT_FAST16_MAX   INT16_MAX
+#define INT_FAST32_MIN   INT32_MIN
+#define INT_FAST32_MAX   INT32_MAX
+#define INT_FAST64_MIN   INT64_MIN
+#define INT_FAST64_MAX   INT64_MAX
+#define UINT_FAST8_MAX   UINT8_MAX
+#define UINT_FAST16_MAX  UINT16_MAX
+#define UINT_FAST32_MAX  UINT32_MAX
+#define UINT_FAST64_MAX  UINT64_MAX
+
+// 7.18.2.4 Limits of integer types capable of holding object pointers
+#ifdef _WIN64 // [
+#  define INTPTR_MIN   INT64_MIN
+#  define INTPTR_MAX   INT64_MAX
+#  define UINTPTR_MAX  UINT64_MAX
+#else // _WIN64 ][
+#  define INTPTR_MIN   INT32_MIN
+#  define INTPTR_MAX   INT32_MAX
+#  define UINTPTR_MAX  UINT32_MAX
+#endif // _WIN64 ]
+
+// 7.18.2.5 Limits of greatest-width integer types
+#define INTMAX_MIN   INT64_MIN
+#define INTMAX_MAX   INT64_MAX
+#define UINTMAX_MAX  UINT64_MAX
+
+// 7.18.3 Limits of other integer types
+
+#ifdef _WIN64 // [
+#  define PTRDIFF_MIN  _I64_MIN
+#  define PTRDIFF_MAX  _I64_MAX
+#else  // _WIN64 ][
+#  define PTRDIFF_MIN  _I32_MIN
+#  define PTRDIFF_MAX  _I32_MAX
+#endif  // _WIN64 ]
+
+#define SIG_ATOMIC_MIN  INT_MIN
+#define SIG_ATOMIC_MAX  INT_MAX
+
+#ifndef SIZE_MAX // [
+#  ifdef _WIN64 // [
+#     define SIZE_MAX  _UI64_MAX
+#  else // _WIN64 ][
+#     define SIZE_MAX  _UI32_MAX
+#  endif // _WIN64 ]
+#endif // SIZE_MAX ]
+
+// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
+#ifndef WCHAR_MIN // [
+#  define WCHAR_MIN  0
+#endif  // WCHAR_MIN ]
+#ifndef WCHAR_MAX // [
+#  define WCHAR_MAX  _UI16_MAX
+#endif  // WCHAR_MAX ]
+
+#define WINT_MIN  0
+#define WINT_MAX  _UI16_MAX
+
+#endif // __STDC_LIMIT_MACROS ]
+
+
+// 7.18.4 Limits of other integer types
+
+#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [   See footnote 224 at page 260
+
+// 7.18.4.1 Macros for minimum-width integer constants
+
+#define INT8_C(val)  val##i8
+#define INT16_C(val) val##i16
+#define INT32_C(val) val##i32
+#define INT64_C(val) val##i64
+
+#define UINT8_C(val)  val##ui8
+#define UINT16_C(val) val##ui16
+#define UINT32_C(val) val##ui32
+#define UINT64_C(val) val##ui64
+
+// 7.18.4.2 Macros for greatest-width integer constants
+#define INTMAX_C   INT64_C
+#define UINTMAX_C  UINT64_C
+
+#endif // __STDC_CONSTANT_MACROS ]
+
+
+#endif // _MSC_STDINT_H_ ]

+ 0 - 0
myaxtls/sha256.c


برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است