Solved

muldiv  long*long/long on 8086

Posted on 1998-05-29
12
399 Views
Last Modified: 2008-02-01
Hello Experts,

I am looking for 64-Bit fixed point arithmetic for 16-Bit compilers (borland)
to implement a  function

long muldiv(long a, long b, long c)   // computing (a*b)/c

The problem is there is no 64 arithmetic for the 16-bit compiler.

Any suggestions are welcome

Thanks in advance.

Michael
 
0
Comment
Question by:m_sauer
  • 4
  • 3
  • 3
  • +1
12 Comments
 
LVL 3

Expert Comment

by:Norbert
ID: 1251049
Answer is comming
0
 
LVL 3

Expert Comment

by:Norbert
ID: 1251050
what about
long muldiv(long a, long b, long c)
{
      return(long)(((double)a*(double)b)/(double)c);
}
this will convert a,b,c to double, calculate the value as double
and convert back to long
0
 
LVL 16

Expert Comment

by:imladris
ID: 1251051
I have a routine (that has been used in a commercial package for years now) that allows for a 48 bit intermediate result (i.e. the multiplication of a and b can be up to 48 bits).
It's not quite the 64 bit intermediate result you asked, on the other hand it is working debugged (Microsoft C) code. It should be easy to adapt. I don't know what kind of numbers you are working with, but 48 bits has been enough in our case.

Let me know if this would be sufficient for your purposes.

0
 
LVL 3

Expert Comment

by:Norbert
ID: 1251052
what about
long muldiv(long a, long b, long c)
{
      return(long)(((double)a*(double)b)/(double)c);
}
this will convert a,b,c to double, calculate the value as double
and convert back to long
0
 
LVL 3

Expert Comment

by:Norbert
ID: 1251053
sorry for duplicate message but the explorer faild the first time
I clicked the submit button
0
 
LVL 10

Expert Comment

by:RONSLOW
ID: 1251054
goto www.snippets.org

they have source code for long integers arithmetic etc.

0
Zoho SalesIQ

Hassle-free live chat software re-imagined for business growth. 2 users, always free.

 
LVL 10

Expert Comment

by:RONSLOW
ID: 1251055
In particular you will find there

|=============================================================================
| Cliff Rhodes' package of unsigned integer math for arbitrarily large numbers
|=============================================================================
| File         O/S  Description
| ------------ ---  ----------------------------------------------------------
  Bignum.H     any  Header declaring the BigNum struct and prototypes
  Bignum1.C    any  Add, subtract, and multiply BigNum's
  Bignum2.C    any  Divide BigNum's
  Bigtest.C    any  Test and demo program using BigNum's

0
 
LVL 10

Expert Comment

by:RONSLOW
ID: 1251056
This is arbitrary precision arithmetic .. not 64 bit.

You may need to go to assembly to get efficient 64bit arithmetic.


0
 

Author Comment

by:m_sauer
ID: 1251057
Norbert,
thanks for your suggestion, but this is not really solving my problem.
Double precision floating point is just to slow on the 80188em processor I am using.
It has to be a pure integer solution, as I was asking for.

Thanks anyway.




0
 

Author Comment

by:m_sauer
ID: 1251058
Imladris

the 48-bit routines would be perfect as my intermediate results will fit into that precision.

Please give me some more information!


0
 
LVL 16

Accepted Solution

by:
imladris earned 300 total points
ID: 1251059
The following code is used under Microsoft version 6.0. If your compiler doesn't have
an inline assembler you can eliminate the _asm portion. It is only there to
provide fast results for the case where both arguments are in fact 16 bits or less.
The type argument controls rounding: 0 is regular, 1 is truncate and 2 is round up.
If all you need is regular rounding, simply eliminate the argument and code associated
with all the types except 0. If there's anything else I can explain, please feel free
to ask.


#define Lo(x)    ((x)&0x0000ffffL)
#define Hi(x)    ((x)>>16)

long rmuldiv(a,b,c,type)
long a,b,c;
char type;

{      int i,sgn;
      unsigned long f;
      unsigned long ih,im,il,rh,rl,r;
      long rnd;
      
      if (type==1) rnd=0;
      else if (type==2) rnd=(c>=0?c-1:c+1);
      else rnd=c>>1;

      if(c==0)return(0);
      if((a&0xffff0000L) && (b&0xffff0000L))goto lsovf;
      _asm
      {      mov      ax,word ptr a+2            ;Hi(a)
            mov      cx,word ptr b+2            ;Hi(b)
            or      cx,ax                        ;if both 0
            mov      cx,word ptr b            ;(Lo(b))
            jnz      fulmul                        ;is false do full multiplication
                                                ;note: fulmul also done for any negative numbers
            mov      ax,word ptr a            ;else Lo(a)
            mul      cx                              ;16 bit multiply with overflow is enough
            jmp      scs                              ;goto finish
            
                                    ;The intermediate results of the hi*lo multiplies
                                    ;will be added in to the upper word of the long
                                    ;result and must therefore be 16 bits or less in order
                                    ;to avoid overflow

sovf:      jmp lsovf
fulmul:      mul      cx                              ;Hi(a) * Lo(b)
            jo      sovf
            mov      bx,ax                        ;save intermediate
            mov      ax,word ptr a            ;Lo(a)
            mul      word ptr b+2            ;Lo(a) * Hi(b)
            jo      sovf
            add      bx,ax                        ;add to intermediate
            jc      sovf
            mov      ax,word ptr a
            mul      cx                              ;Lo(a) * Lo(b)
            add      dx,bx                        ;add intermediate to lo multiply
            jc      sovf
      scs:
            mov      word ptr f,ax
            mov      word ptr f+2,dx
      }

      if(c>=0)return((f+rnd)/c);
      return((f-rnd)/c);

lsovf:
/* resolve sign result beforehand, so that this routine can
   assume working with 2 non-negative quantities
*/
      sgn=1;
      if(a<0)
      {      a=-a;
            sgn*=-1;
      }
      if(b<0)
      {      b=-b;
            sgn*=-1;
      }
      if(c<0)
      {      c=-c;
            rnd=-rnd;
            sgn*=-1;
      }
      
/* multiply 2 longs by multiplying all the words and adding with
   appropriate shifts.
*/
   
      il=Lo(a)*Lo(b);
      im=Lo(a)*Hi(b)+Hi(a)*Lo(b);
      ih=Hi(a)*Hi(b);
      rl=il+(Lo(im)<<16);
      rh=ih+Hi(im)+(Hi(il)+Lo(im)>0x0000ffffL);

/*  Add rnd , which depends on rounding method */

      il=Lo(rl)+Lo(rnd);
      im=Hi(rl)+Hi(rnd)+Hi(il);
      rl=Lo(il)+(im<<16);
      rh+=Hi(im);

/*      This division routine will deal with a 6 byte number
    It essentially starts off by doing long division:
      If we label the bytes 1 2 3 4 5 6 it first divides
      1 2 3 4 by c giving r the result. The intermediate now
      gets the remainder, and the result is shifted up.
      If this remainder is less than 2 bytes we proceed by
      shifting the intermediate result left, orring in the rest
      of the dividend and orring the result in, just like long division.
      If the result is longer than 2 bytes (which implies that the
      divisor is longer than 2 bytes also) then the shifts we did
      before would shift out high order bits in im.
      Therefore these are put in rh. im is shifted up and gets the rest
      of the dividend orred in. The final result is now obtained by
      bitwise long division.
*/

      r=0;
      im=(rh<<16) | ((rl>>16)&0x0000ffffL);
      r=im/c;
      im%=c;
      r<<=16;
      if((im&0xffff0000L)==0)return(sgn*(long)(r | (im<<16 | rl&0x0000ffffL)/c));
      rh=(im>>16)&0x0000ffffL;
      rl=im<<16 | (rl&0x0000ffffL);
      im=0;
      for(i=0; i<32; ++i)
      {      rh<<=1;
            rh|=(rl&0x80000000L?1:0);
            rl<<=1;
            im<<=1;
            if(rh>c)
            {      rh-=c;
                  ++im;
            }
      }
      return(sgn*(long)(r | im));
}

0
 

Author Comment

by:m_sauer
ID: 1251060
imladris,

just assuming your routine works right (it's too tricky to judge form the source ), it is an excellent solution for my problem.

thank you very much for your great help.


0

Featured Post

ScreenConnect 6.0 Free Trial

Want empowering updates? You're in the right place! Discover new features in ScreenConnect 6.0, based on partner feedback, to keep you business operating smoothly and optimally (the way it should be). Explore all of the extras and enhancements for yourself!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
c language help - file paths 7 141
TCP/IP Socket - connection close results in data lost 14 120
Global Keyboard Hooks Blocked 4 70
C Programming - If Statement 8 72
This tutorial is posted by Aaron Wojnowski, administrator at SDKExpert.net.  To view more iPhone tutorials, visit www.sdkexpert.net. This is a very simple tutorial on finding the user's current location easily. In this tutorial, you will learn ho…
Summary: This tutorial covers some basics of pointer, pointer arithmetic and function pointer. What is a pointer: A pointer is a variable which holds an address. This address might be address of another variable/address of devices/address of fu…
The goal of this video is to provide viewers with basic examples to understand and use structures in the C programming language.
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use while-loops in the C programming language.

920 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now