revert between 56095 -> 55830 in arch
[AROS.git] / workbench / network / smbfs / source_code / quad_math.c
blob3215da54391b0de412b234087efd90e6c0911097
1 /*
2 * $Id$
4 * :ts=4
6 * SMB file system wrapper for AmigaOS, using the AmiTCP V3 API
8 * Copyright (C) 2000-2016 by Olaf `Olsen' Barthel <obarthel -at- gmx -dot- net>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #ifndef _QUAD_MATH_H
26 #include "quad_math.h"
27 #endif /* _QUAD_MATH_H */
29 /****************************************************************************/
31 /* Divide a 64 bit integer by a 32 bit integer, filling in a 64 bit quotient
32 and returning a 32 bit remainder. */
33 ULONG
34 divide_64_by_32(QUAD * dividend,ULONG divisor,QUAD * quotient)
36 QUAD dividend_cdef = (*dividend);
37 ULONG dividend_ab = 0;
38 LONG i;
40 quotient->High = quotient->Low = 0;
42 for(i = 0 ; i < 64 ; i++)
44 /* Shift the quotient left by one bit. */
45 quotient->High = (quotient->High << 1);
47 if((quotient->Low & 0x80000000UL) != 0)
48 quotient->High |= 1;
50 quotient->Low = (quotient->Low << 1);
52 /* Shift the dividend left by one bit. We start
53 * with the most significant 32 bit portion.
55 dividend_ab = (dividend_ab << 1);
57 if((dividend_cdef.High & 0x80000000UL) != 0)
58 dividend_ab |= 1;
60 /* Now for the middle 32 bit portion. */
61 dividend_cdef.High = (dividend_cdef.High << 1);
63 if((dividend_cdef.Low & 0x80000000UL) != 0)
64 dividend_cdef.High |= 1;
66 /* Finally, the least significant portion. */
67 dividend_cdef.Low = (dividend_cdef.Low << 1);
69 /* Does the divisor actually divide the dividend? */
70 if(dividend_ab >= divisor)
72 dividend_ab -= divisor;
74 /* We could divide the divisor. Keep track of
75 * this and take care of an overflow condition.
77 quotient->Low++;
78 if(quotient->Low == 0)
79 quotient->High++;
83 return(dividend_ab);
86 /****************************************************************************/
88 /* Subtract a 64 bit integer from another 64 bit integer, producing a
89 64 bit integer difference, returning a 32 bit integer that indicates
90 whether or not an underflow occured. */
91 ULONG
92 subtract_64_from_64_to_64(const QUAD * const minuend,const QUAD * const subtrahend,QUAD * difference)
94 QUAD extended_minuend;
96 /* We may have to borrow if the minuend is less than the
97 subtrahend, so we set up a local variable to track
98 any underflow this might produce. */
99 extended_minuend.High = 0;
100 extended_minuend.Low = minuend->High;
102 /* First step: take care of the least significant word. If
103 that produces a local underflow, borrow from the most
104 significant word. */
105 if(minuend->Low < subtrahend->Low)
107 /* Borrow, and if there's nothing to be borrowed,
108 remember that we had an underflow. */
109 if(extended_minuend.Low-- == 0)
110 extended_minuend.High--;
113 difference->Low = minuend->Low - subtrahend->Low;
115 /* Second step: take care of the most significant word. If
116 that produces a local underflow, remember that. */
117 if(extended_minuend.Low < subtrahend->High)
118 extended_minuend.High--;
120 difference->High = extended_minuend.Low - subtrahend->High;
122 /* Return the underflow, if any. */
123 return(extended_minuend.High);