• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 418
  • Last Modified:

muldiv long*long/long on 8086

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
m_sauer
Asked:
m_sauer
  • 4
  • 3
  • 3
  • +1
1 Solution
 
NorbertCommented:
Answer is comming
0
 
NorbertCommented:
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
 
imladrisCommented:
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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
NorbertCommented:
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
 
NorbertCommented:
sorry for duplicate message but the explorer faild the first time
I clicked the submit button
0
 
RONSLOWCommented:
goto www.snippets.org

they have source code for long integers arithmetic etc.

0
 
RONSLOWCommented:
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
 
RONSLOWCommented:
This is arbitrary precision arithmetic .. not 64 bit.

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


0
 
m_sauerAuthor Commented:
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
 
m_sauerAuthor Commented:
Imladris

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

Please give me some more information!


0
 
imladrisCommented:
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
 
m_sauerAuthor Commented:
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

Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

  • 4
  • 3
  • 3
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now