2005-04-17 02:20:36 +04:00
/*
* Copyright ( C ) 2003 Bernardo Innocenti < bernie @ develer . com >
*
* Based on former do_div ( ) implementation from asm - parisc / div64 . h :
* Copyright ( C ) 1999 Hewlett - Packard Co
* Copyright ( C ) 1999 David Mosberger - Tang < davidm @ hpl . hp . com >
*
*
* Generic C version of 64 bit / 32 bit division and modulo , with
* 64 bit result and 32 bit remainder .
*
* The fast case for ( n > > 32 = = 0 ) is handled inline by do_div ( ) .
*
* Code generated for this function might be very inefficient
* for some CPUs . __div64_32 ( ) can be overridden by linking arch - specific
2015-11-02 21:02:46 +03:00
* assembly versions such as arch / ppc / lib / div64 . S and arch / sh / lib / div64 . S
* or by defining a preprocessor macro in arch / include / asm / div64 . h .
2005-04-17 02:20:36 +04:00
*/
2011-11-17 06:29:17 +04:00
# include <linux/export.h>
# include <linux/kernel.h>
2008-05-01 15:34:25 +04:00
# include <linux/math64.h>
2005-04-17 02:20:36 +04:00
/* Not needed on 64bit architectures */
# if BITS_PER_LONG == 32
2015-11-02 21:02:46 +03:00
# ifndef __div64_32
2007-04-11 09:10:39 +04:00
uint32_t __attribute__ ( ( weak ) ) __div64_32 ( uint64_t * n , uint32_t base )
2005-04-17 02:20:36 +04:00
{
uint64_t rem = * n ;
uint64_t b = base ;
uint64_t res , d = 1 ;
uint32_t high = rem > > 32 ;
/* Reduce the thing a bit first */
res = 0 ;
if ( high > = base ) {
high / = base ;
res = ( uint64_t ) high < < 32 ;
rem - = ( uint64_t ) ( high * base ) < < 32 ;
}
while ( ( int64_t ) b > 0 & & b < rem ) {
b = b + b ;
d = d + d ;
}
do {
if ( rem > = b ) {
rem - = b ;
res + = d ;
}
b > > = 1 ;
d > > = 1 ;
} while ( d ) ;
* n = res ;
return rem ;
}
EXPORT_SYMBOL ( __div64_32 ) ;
2015-11-02 21:02:46 +03:00
# endif
2005-04-17 02:20:36 +04:00
2008-05-01 15:34:25 +04:00
# ifndef div_s64_rem
s64 div_s64_rem ( s64 dividend , s32 divisor , s32 * remainder )
{
u64 quotient ;
if ( dividend < 0 ) {
quotient = div_u64_rem ( - dividend , abs ( divisor ) , ( u32 * ) remainder ) ;
* remainder = - * remainder ;
if ( divisor > 0 )
quotient = - quotient ;
} else {
quotient = div_u64_rem ( dividend , abs ( divisor ) , ( u32 * ) remainder ) ;
if ( divisor < 0 )
quotient = - quotient ;
}
return quotient ;
}
EXPORT_SYMBOL ( div_s64_rem ) ;
# endif
2013-08-20 23:05:17 +04:00
/**
* div64_u64_rem - unsigned 64 bit divide with 64 bit divisor and remainder
* @ dividend : 64 bit dividend
* @ divisor : 64 bit divisor
* @ remainder : 64 bit remainder
*
* This implementation is a comparable to algorithm used by div64_u64 .
* But this operation , which includes math for calculating the remainder ,
* is kept distinct to avoid slowing down the div64_u64 operation on 32 bit
* systems .
*/
# ifndef div64_u64_rem
u64 div64_u64_rem ( u64 dividend , u64 divisor , u64 * remainder )
{
u32 high = divisor > > 32 ;
u64 quot ;
if ( high = = 0 ) {
u32 rem32 ;
quot = div_u64_rem ( dividend , divisor , & rem32 ) ;
* remainder = rem32 ;
} else {
int n = 1 + fls ( high ) ;
quot = div_u64 ( dividend > > n , divisor > > n ) ;
if ( quot ! = 0 )
quot - - ;
* remainder = dividend - quot * divisor ;
if ( * remainder > = divisor ) {
quot + + ;
* remainder - = divisor ;
}
}
return quot ;
}
EXPORT_SYMBOL ( div64_u64_rem ) ;
# endif
2010-10-27 01:23:10 +04:00
/**
2013-04-30 13:35:07 +04:00
* div64_u64 - unsigned 64 bit divide with 64 bit divisor
2010-10-27 01:23:10 +04:00
* @ dividend : 64 bit dividend
* @ divisor : 64 bit divisor
*
* This implementation is a modified version of the algorithm proposed
* by the book ' Hacker ' s Delight ' . The original source and full proof
* can be found here and is available for use without restriction .
*
2015-02-26 22:19:03 +03:00
* ' http : //www.hackersdelight.org/hdcodetxt/divDouble.c.txt'
2010-10-27 01:23:10 +04:00
*/
2013-04-30 13:35:07 +04:00
# ifndef div64_u64
u64 div64_u64 ( u64 dividend , u64 divisor )
2007-03-26 06:54:23 +04:00
{
2010-10-27 01:23:10 +04:00
u32 high = divisor > > 32 ;
u64 quot ;
2007-03-26 06:54:23 +04:00
2010-10-27 01:23:10 +04:00
if ( high = = 0 ) {
2013-04-30 13:35:07 +04:00
quot = div_u64 ( dividend , divisor ) ;
2010-10-27 01:23:10 +04:00
} else {
int n = 1 + fls ( high ) ;
quot = div_u64 ( dividend > > n , divisor > > n ) ;
2007-03-26 06:54:23 +04:00
2010-10-27 01:23:10 +04:00
if ( quot ! = 0 )
quot - - ;
2013-04-30 13:35:07 +04:00
if ( ( dividend - quot * divisor ) > = divisor )
2010-10-27 01:23:10 +04:00
quot + + ;
}
2007-03-26 06:54:23 +04:00
2010-10-27 01:23:10 +04:00
return quot ;
2007-03-26 06:54:23 +04:00
}
2013-04-30 13:35:07 +04:00
EXPORT_SYMBOL ( div64_u64 ) ;
2008-05-01 15:34:28 +04:00
# endif
2007-03-26 06:54:23 +04:00
2010-10-27 01:23:10 +04:00
/**
* div64_s64 - signed 64 bit divide with 64 bit divisor
* @ dividend : 64 bit dividend
* @ divisor : 64 bit divisor
*/
# ifndef div64_s64
s64 div64_s64 ( s64 dividend , s64 divisor )
{
s64 quot , t ;
2015-11-10 01:58:13 +03:00
quot = div64_u64 ( abs ( dividend ) , abs ( divisor ) ) ;
2010-10-27 01:23:10 +04:00
t = ( dividend ^ divisor ) > > 63 ;
return ( quot ^ t ) - t ;
}
EXPORT_SYMBOL ( div64_s64 ) ;
# endif
2005-04-17 02:20:36 +04:00
# endif /* BITS_PER_LONG == 32 */
2008-06-12 12:47:56 +04:00
/*
* Iterative div / mod for use when dividend is not expected to be much
* bigger than divisor .
*/
u32 iter_div_u64_rem ( u64 dividend , u32 divisor , u64 * remainder )
{
2008-06-12 12:47:58 +04:00
return __iter_div_u64_rem ( dividend , divisor , remainder ) ;
2008-06-12 12:47:56 +04:00
}
EXPORT_SYMBOL ( iter_div_u64_rem ) ;