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

📄 arith.c

📁 远程桌面连接工具
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $XConsortium: arith.c,v 1.4 94/03/22 19:08:54 gildea Exp $ *//* Copyright International Business Machines, Corp. 1991 * All Rights Reserved * Copyright Lexmark International, Inc. 1991 * All Rights Reserved * * License to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation, and that the name of IBM or Lexmark not be * used in advertising or publicity pertaining to distribution of the * software without specific, written prior permission. * * IBM AND LEXMARK PROVIDE THIS SOFTWARE "AS IS", WITHOUT ANY WARRANTIES OF * ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO ANY * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, * AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.  THE ENTIRE RISK AS TO THE * QUALITY AND PERFORMANCE OF THE SOFTWARE, INCLUDING ANY DUTY TO SUPPORT * OR MAINTAIN, BELONGS TO THE LICENSEE.  SHOULD ANY PORTION OF THE * SOFTWARE PROVE DEFECTIVE, THE LICENSEE (NOT IBM OR LEXMARK) ASSUMES THE * ENTIRE COST OF ALL SERVICING, REPAIR AND CORRECTION.  IN NO EVENT SHALL * IBM OR LEXMARK BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF * THIS SOFTWARE. */ /* ARITH    CWEB         V0006 ********                             *//*:h1.ARITH Module - Portable Module for Multiple Precision Fixed Point Arithmetic This module provides division and multiplication of 64-bit fixed pointnumbers.  (To be more precise, the module works on numbers that taketwo 'longs' to store.  That is almost always equivalent to saying 64-bitnumbers.) Note: it is frequently easy and desirable to recode these functions inassembly language for the particular processor being used, becauseassembly language, unlike C, will have 64-bit multiply products and64-bit dividends.  This module is offered as a portable version. &author. Jeffrey B. Lotspiech (lotspiech@almaden.ibm.com) and Sten F. Andler  :h3.Include Files The included files are:*/ #include "objects.h"#include "spaces.h"#include "arith.h" /*:h3.*//*SHARED LINE(S) ORIGINATED HERE*//*Reference for all algorithms:  Donald E. Knuth, "The Art of ComputerProgramming, Volume 2, Semi-Numerical Algorithms," Addison-Wesley Co.,Massachusetts, 1969, pp. 229-279. Knuth talks about a 'digit' being an arbitrary sized unit and a numberbeing a sequence of digits.  We'll take a digit to be a 'short'.The following assumption must be valid for these algorithms to work::ol.:li.A 'long' is two 'short's.:eol.The following code is INDEPENDENT of::ol.:li.The actual size of a short.:li.Whether shorts and longs are stored most significant bytefirst or least significant byte first.:eol. SHORTSIZE is the number of bits in a short; LONGSIZE is the number ofbits in a long; MAXSHORT is the maximum unsigned short:*//*SHARED LINE(S) ORIGINATED HERE*//*ASSEMBLE concatenates two shorts to form a long:*/#define     ASSEMBLE(hi,lo)   ((((unsigned long)hi)<<SHORTSIZE)+(lo))/*HIGHDIGIT extracts the most significant short from a long; LOWDIGITextracts the least significant short from a long:*/#define     HIGHDIGIT(u)      ((u)>>SHORTSIZE)#define     LOWDIGIT(u)       ((u)&MAXSHORT) /*SIGNBITON tests the high order bit of a long 'w':*/#define    SIGNBITON(w)   (((long)w)<0) /*SHARED LINE(S) ORIGINATED HERE*/ /*:h2.Double Long Arithmetic :h3.DLmult() - Multiply Two Longs to Yield a Double Long The two multiplicands must be positive.*/ void DLmult(product, u, v)  register doublelong *product;  register unsigned long u;  register unsigned long v;{#ifdef LONG64/* printf("DLmult(? ?, %lx, %lx)\n", u, v); */    *product = u*v;/* printf("DLmult returns %lx\n", *product); */#else  register unsigned long u1, u2; /* the digits of u */  register unsigned long v1, v2; /* the digits of v */  register unsigned int w1, w2, w3, w4; /* the digits of w */  register unsigned long t; /* temporary variable *//* printf("DLmult(? ?, %x, %x)\n", u, v); */  u1 = HIGHDIGIT(u);  u2 = LOWDIGIT(u);  v1 = HIGHDIGIT(v);  v2 = LOWDIGIT(v);   if (v2 == 0) w4 = w3 = w2 = 0;  else    {    t = u2 * v2;    w4 = LOWDIGIT(t);    t = u1 * v2 + HIGHDIGIT(t);    w3 = LOWDIGIT(t);    w2 = HIGHDIGIT(t);    }   if (v1 == 0) w1 = 0;  else    {    t = u2 * v1 + w3;    w3 = LOWDIGIT(t);    t = u1 * v1 + w2 + HIGHDIGIT(t);    w2 = LOWDIGIT(t);    w1 = HIGHDIGIT(t);    }   product->high = ASSEMBLE(w1, w2);  product->low  = ASSEMBLE(w3, w4);#endif /* LONG64 else */} /*:h2.DLdiv() - Divide Two Longs by One Long, Yielding Two Longs Both the dividend and the divisor must be positive.*/ void DLdiv(quotient, divisor)       doublelong *quotient;       /* also where dividend is, originally     */       unsigned long divisor;{#ifdef LONG64/* printf("DLdiv(%lx %lx)\n", quotient, divisor); */	*quotient /= divisor;/* printf("DLdiv returns %lx\n", *quotient); */#else       register unsigned long u1u2 = quotient->high;       register unsigned long u3u4 = quotient->low;       register long u3;     /* single digit of dividend                     */       register int v1,v2;   /* divisor in registers                         */       register long t;      /* signed copy of u1u2                          */       register int qhat;    /* guess at the quotient digit                  */       register unsigned long q3q4;  /* low two digits of quotient           */       register int shift;   /* holds the shift value for normalizing        */       register int j;       /* loop variable                                */ /* printf("DLdiv(%x %x, %x)\n", quotient->high, quotient->low, divisor); */       /*       * Knuth's algorithm works if the dividend is smaller than the       * divisor.  We can get to that state quickly:       */       if (u1u2 >= divisor) {               quotient->high = u1u2 / divisor;               u1u2 %= divisor;       }       else               quotient->high = 0;        if (divisor <= MAXSHORT) {                /*               * This is the case where the divisor is contained in one               * 'short'.  It is worthwhile making this fast:               */               u1u2 = ASSEMBLE(u1u2, HIGHDIGIT(u3u4));               q3q4 = u1u2 / divisor;               u1u2 %= divisor;               u1u2 = ASSEMBLE(u1u2, LOWDIGIT(u3u4));               quotient->low = ASSEMBLE(q3q4, u1u2 / divisor);               return;       }         /*       * At this point the divisor is a true 'long' so we must use       * Knuth's algorithm.       *       * Step D1: Normalize divisor and dividend (this makes our 'qhat'       *        guesses more accurate):       */       for (shift=0; !SIGNBITON(divisor); shift++, divisor <<= 1) { ; }       shift--;       divisor >>= 1;        if ((u1u2 >> (LONGSIZE - shift)) != 0 && shift != 0)               abort("DLdiv:  dividend too large");       u1u2 = (u1u2 << shift) + ((shift == 0) ? 0 : u3u4 >> (LONGSIZE - shift));       u3u4 <<= shift;        /*       * Step D2:  Begin Loop through digits, dividing u1,u2,u3 by v1,v2,       *           then shifting U left by 1 digit:       */       v1 = HIGHDIGIT(divisor);       v2 = LOWDIGIT(divisor);       q3q4 = 0;       u3 = HIGHDIGIT(u3u4);        for (j=0; j < 2; j++) {                /*               * Step D3:  make a guess (qhat) at the next quotient denominator:               */               qhat = (HIGHDIGIT(u1u2) == v1) ? MAXSHORT : u1u2 / v1;               /*               * At this point Knuth would have us further refine our               * guess, since we know qhat is too big if               *               *      v2 * qhat > ASSEMBLE(u1u2 % v, u3)               *               * That would make sense if u1u2 % v was easy to find, as it               * would be in assembly language.  I ignore this step, and               * repeat step D6 if qhat is too big.

⌨️ 快捷键说明

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