Merge pull request #2309 from mitza-oci/warnings
[ACE_TAO.git] / ACE / ace / CDR_Base.cpp
blobe5e96bdd8bc1724f6b9b7cd31d64eb44c8bb71e1
1 #include "ace/CDR_Base.h"
3 #if !defined (__ACE_INLINE__)
4 # include "ace/CDR_Base.inl"
5 #endif /* ! __ACE_INLINE__ */
7 #include "ace/Message_Block.h"
8 #include "ace/OS_Memory.h"
9 #include "ace/OS_NS_string.h"
11 #ifdef ACE_LACKS_IOSTREAM_TOTALLY
12 #include "ace/OS_NS_stdio.h"
13 #else
14 #include "ace/streams.h"
15 #endif
17 #include <cmath>
18 #include <cstring>
19 #include <limits>
20 #include <algorithm>
22 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
24 #if defined (NONNATIVE_LONGDOUBLE)
25 static constexpr ACE_INT16 max_eleven_bit = 0x3ff;
26 static constexpr ACE_INT16 max_fifteen_bit = 0x3fff;
27 #endif /* NONNATIVE_LONGDOUBLE */
29 // See comments in CDR_Base.inl about optimization cases for swap_XX_array.
30 void
31 ACE_CDR::swap_2_array (char const * orig, char* target, size_t n)
33 // ACE_ASSERT(n > 0); The caller checks that n > 0
35 // We pretend that AMD64/GNU G++ systems have a Pentium CPU to
36 // take advantage of the inline assembly implementation.
38 // Later, we try to read in 32 or 64 bit chunks,
39 // so make sure we don't do that for unaligned addresses.
40 #if ACE_SIZEOF_LONG == 8 && \
41 !((defined(__amd64__) || defined (__x86_64__)) && defined(__GNUG__))
42 char const * const o8 = ACE_ptr_align_binary (orig, 8);
43 while (orig < o8 && n > 0)
45 ACE_CDR::swap_2 (orig, target);
46 orig += 2;
47 target += 2;
48 --n;
50 #else
51 char const * const o4 = ACE_ptr_align_binary (orig, 4);
52 // this is an _if_, not a _while_. The mismatch can only be by 2.
53 if (orig != o4)
55 ACE_CDR::swap_2 (orig, target);
56 orig += 2;
57 target += 2;
58 --n;
60 #endif
61 if (n == 0)
62 return;
65 // Loop unrolling. Here be dragons.
68 // (n & (~3)) is the greatest multiple of 4 not bigger than n.
69 // In the while loop ahead, orig will move over the array by 8 byte
70 // increments (4 elements of 2 bytes).
71 // end marks our barrier for not falling outside.
72 char const * const end = orig + 2 * (n & (~3));
74 // See if we're aligned for writing in 64 or 32 bit chunks...
75 #if ACE_SIZEOF_LONG == 8 && \
76 !((defined(__amd64__) || defined (__x86_64__)) && defined(__GNUG__))
77 if (target == ACE_ptr_align_binary (target, 8))
78 #else
79 if (target == ACE_ptr_align_binary (target, 4))
80 #endif
82 while (orig < end)
84 #if defined (ACE_HAS_INTEL_ASSEMBLY)
85 unsigned int a =
86 * reinterpret_cast<const unsigned int*> (orig);
87 unsigned int b =
88 * reinterpret_cast<const unsigned int*> (orig + 4);
89 asm ( "bswap %1" : "=r" (a) : "0" (a) );
90 asm ( "bswap %1" : "=r" (b) : "0" (b) );
91 asm ( "rol $16, %1" : "=r" (a) : "0" (a) );
92 asm ( "rol $16, %1" : "=r" (b) : "0" (b) );
93 * reinterpret_cast<unsigned int*> (target) = a;
94 * reinterpret_cast<unsigned int*> (target + 4) = b;
95 #elif defined(ACE_HAS_PENTIUM) \
96 && (defined(_MSC_VER) || defined(__BORLANDC__)) \
97 && !defined(ACE_LACKS_INLINE_ASSEMBLY)
98 __asm mov ecx, orig;
99 __asm mov edx, target;
100 __asm mov eax, [ecx];
101 __asm mov ebx, 4[ecx];
102 __asm bswap eax;
103 __asm bswap ebx;
104 __asm rol eax, 16;
105 __asm rol ebx, 16;
106 __asm mov [edx], eax;
107 __asm mov 4[edx], ebx;
108 #elif ACE_SIZEOF_LONG == 8
109 // 64 bit architecture.
110 unsigned long a = * reinterpret_cast<const unsigned long*> (orig);
112 unsigned long a1 = (a & 0x00ff00ff00ff00ffUL) << 8;
113 unsigned long a2 = (a & 0xff00ff00ff00ff00UL) >> 8;
115 a = (a1 | a2);
117 * reinterpret_cast<unsigned long*> (target) = a;
118 #else
119 ACE_UINT32 a = * reinterpret_cast<const ACE_UINT32*> (orig);
120 ACE_UINT32 b = * reinterpret_cast<const ACE_UINT32*> (orig + 4);
122 ACE_UINT32 a1 = (a & 0x00ff00ffU) << 8;
123 ACE_UINT32 b1 = (b & 0x00ff00ffU) << 8;
124 ACE_UINT32 a2 = (a & 0xff00ff00U) >> 8;
125 ACE_UINT32 b2 = (b & 0xff00ff00U) >> 8;
127 a = (a1 | a2);
128 b = (b1 | b2);
130 * reinterpret_cast<ACE_UINT32*> (target) = a;
131 * reinterpret_cast<ACE_UINT32*> (target + 4) = b;
132 #endif
133 orig += 8;
134 target += 8;
137 else
139 // We're out of luck. We have to write in 2 byte chunks.
140 while (orig < end)
142 #if defined (ACE_HAS_INTEL_ASSEMBLY)
143 unsigned int a =
144 * reinterpret_cast<const unsigned int*> (orig);
145 unsigned int b =
146 * reinterpret_cast<const unsigned int*> (orig + 4);
147 asm ( "bswap %1" : "=r" (a) : "0" (a) );
148 asm ( "bswap %1" : "=r" (b) : "0" (b) );
149 // We're little endian.
150 * reinterpret_cast<unsigned short*> (target + 2)
151 = (unsigned short) (a & 0xffff);
152 * reinterpret_cast<unsigned short*> (target + 6)
153 = (unsigned short) (b & 0xffff);
154 asm ( "shrl $16, %1" : "=r" (a) : "0" (a) );
155 asm ( "shrl $16, %1" : "=r" (b) : "0" (b) );
156 * reinterpret_cast<unsigned short*> (target + 0)
157 = (unsigned short) (a & 0xffff);
158 * reinterpret_cast<unsigned short*> (target + 4)
159 = (unsigned short) (b & 0xffff);
160 #elif defined (ACE_HAS_PENTIUM) \
161 && (defined (_MSC_VER) || defined (__BORLANDC__)) \
162 && !defined (ACE_LACKS_INLINE_ASSEMBLY)
163 __asm mov ecx, orig;
164 __asm mov edx, target;
165 __asm mov eax, [ecx];
166 __asm mov ebx, 4[ecx];
167 __asm bswap eax;
168 __asm bswap ebx;
169 // We're little endian.
170 __asm mov 2[edx], ax;
171 __asm mov 6[edx], bx;
172 __asm shr eax, 16;
173 __asm shr ebx, 16;
174 __asm mov 0[edx], ax;
175 __asm mov 4[edx], bx;
176 #elif ACE_SIZEOF_LONG == 8
177 // 64 bit architecture.
178 unsigned long a = * reinterpret_cast<const unsigned long*> (orig);
180 unsigned long a1 = (a & 0x00ff00ff00ff00ffUL) << 8;
181 unsigned long a2 = (a & 0xff00ff00ff00ff00UL) >> 8;
183 a = (a1 | a2);
185 ACE_UINT16 b1 = static_cast<ACE_UINT16> (a >> 48);
186 ACE_UINT16 b2 = static_cast<ACE_UINT16> ((a >> 32) & 0xffff);
187 ACE_UINT16 b3 = static_cast<ACE_UINT16> ((a >> 16) & 0xffff);
188 ACE_UINT16 b4 = static_cast<ACE_UINT16> (a & 0xffff);
190 #if defined(ACE_LITTLE_ENDIAN)
191 * reinterpret_cast<ACE_UINT16*> (target) = b4;
192 * reinterpret_cast<ACE_UINT16*> (target + 2) = b3;
193 * reinterpret_cast<ACE_UINT16*> (target + 4) = b2;
194 * reinterpret_cast<ACE_UINT16*> (target + 6) = b1;
195 #else
196 * reinterpret_cast<ACE_UINT16*> (target) = b1;
197 * reinterpret_cast<ACE_UINT16*> (target + 2) = b2;
198 * reinterpret_cast<ACE_UINT16*> (target + 4) = b3;
199 * reinterpret_cast<ACE_UINT16*> (target + 6) = b4;
200 #endif
201 #else
202 ACE_UINT32 a = * reinterpret_cast<const ACE_UINT32*> (orig);
203 ACE_UINT32 b = * reinterpret_cast<const ACE_UINT32*> (orig + 4);
205 ACE_UINT32 a1 = (a & 0x00ff00ff) << 8;
206 ACE_UINT32 b1 = (b & 0x00ff00ff) << 8;
207 ACE_UINT32 a2 = (a & 0xff00ff00) >> 8;
208 ACE_UINT32 b2 = (b & 0xff00ff00) >> 8;
210 a = (a1 | a2);
211 b = (b1 | b2);
213 ACE_UINT32 c1 = static_cast<ACE_UINT16> (a >> 16);
214 ACE_UINT32 c2 = static_cast<ACE_UINT16> (a & 0xffff);
215 ACE_UINT32 c3 = static_cast<ACE_UINT16> (b >> 16);
216 ACE_UINT32 c4 = static_cast<ACE_UINT16> (b & 0xffff);
218 #if defined(ACE_LITTLE_ENDIAN)
219 * reinterpret_cast<ACE_UINT16*> (target) = c2;
220 * reinterpret_cast<ACE_UINT16*> (target + 2) = c1;
221 * reinterpret_cast<ACE_UINT16*> (target + 4) = c4;
222 * reinterpret_cast<ACE_UINT16*> (target + 6) = c3;
223 #else
224 * reinterpret_cast<ACE_UINT16*> (target) = c1;
225 * reinterpret_cast<ACE_UINT16*> (target + 2) = c2;
226 * reinterpret_cast<ACE_UINT16*> (target + 4) = c3;
227 * reinterpret_cast<ACE_UINT16*> (target + 6) = c4;
228 #endif
229 #endif
231 orig += 8;
232 target += 8;
236 // (n & 3) == (n % 4).
237 switch (n&3) {
238 case 3:
239 ACE_CDR::swap_2 (orig, target);
240 orig += 2;
241 target += 2;
242 ACE_FALLTHROUGH;
243 case 2:
244 ACE_CDR::swap_2 (orig, target);
245 orig += 2;
246 target += 2;
247 ACE_FALLTHROUGH;
248 case 1:
249 ACE_CDR::swap_2 (orig, target);
253 void
254 ACE_CDR::swap_4_array (char const * orig, char* target, size_t n)
256 // ACE_ASSERT (n > 0); The caller checks that n > 0
258 #if ACE_SIZEOF_LONG == 8
259 // Later, we read from *orig in 64 bit chunks,
260 // so make sure we don't generate unaligned readings.
261 char const * const o8 = ACE_ptr_align_binary (orig, 8);
262 // The mismatch can only be by 4.
263 if (orig != o8)
265 ACE_CDR::swap_4 (orig, target);
266 orig += 4;
267 target += 4;
268 --n;
270 #endif /* ACE_SIZEOF_LONG == 8 */
272 if (n == 0)
273 return;
276 // Loop unrolling. Here be dragons.
279 // (n & (~3)) is the greatest multiple of 4 not bigger than n.
280 // In the while loop, orig will move over the array by 16 byte
281 // increments (4 elements of 4 bytes).
282 // ends marks our barrier for not falling outside.
283 char const * const end = orig + 4 * (n & (~3));
285 #if ACE_SIZEOF_LONG == 8
286 // 64 bits architecture.
287 // See if we can write in 8 byte chunks.
288 if (target == ACE_ptr_align_binary (target, 8))
290 while (orig < end)
292 unsigned long a = * reinterpret_cast<const long*> (orig);
293 unsigned long b = * reinterpret_cast<const long*> (orig + 8);
295 #if defined(ACE_HAS_INTEL_ASSEMBLY)
296 asm ("bswapq %1" : "=r" (a) : "0" (a));
297 asm ("bswapq %1" : "=r" (b) : "0" (b));
298 asm ("rol $32, %1" : "=r" (a) : "0" (a));
299 asm ("rol $32, %1" : "=r" (b) : "0" (b));
300 #else
301 unsigned long a84 = (a & 0x000000ff000000ffL) << 24;
302 unsigned long b84 = (b & 0x000000ff000000ffL) << 24;
303 unsigned long a73 = (a & 0x0000ff000000ff00L) << 8;
304 unsigned long b73 = (b & 0x0000ff000000ff00L) << 8;
305 unsigned long a62 = (a & 0x00ff000000ff0000L) >> 8;
306 unsigned long b62 = (b & 0x00ff000000ff0000L) >> 8;
307 unsigned long a51 = (a & 0xff000000ff000000L) >> 24;
308 unsigned long b51 = (b & 0xff000000ff000000L) >> 24;
310 a = (a84 | a73 | a62 | a51);
311 b = (b84 | b73 | b62 | b51);
312 #endif
314 * reinterpret_cast<long*> (target) = a;
315 * reinterpret_cast<long*> (target + 8) = b;
317 orig += 16;
318 target += 16;
321 else
323 // We are out of luck, we have to write in 4 byte chunks.
324 while (orig < end)
326 unsigned long a = * reinterpret_cast<const long*> (orig);
327 unsigned long b = * reinterpret_cast<const long*> (orig + 8);
329 #if defined(ACE_HAS_INTEL_ASSEMBLY)
330 asm ("bswapq %1" : "=r" (a) : "0" (a));
331 asm ("bswapq %1" : "=r" (b) : "0" (b));
332 asm ("rol $32, %1" : "=r" (a) : "0" (a));
333 asm ("rol $32, %1" : "=r" (b) : "0" (b));
334 #else
335 unsigned long a84 = (a & 0x000000ff000000ffL) << 24;
336 unsigned long b84 = (b & 0x000000ff000000ffL) << 24;
337 unsigned long a73 = (a & 0x0000ff000000ff00L) << 8;
338 unsigned long b73 = (b & 0x0000ff000000ff00L) << 8;
339 unsigned long a62 = (a & 0x00ff000000ff0000L) >> 8;
340 unsigned long b62 = (b & 0x00ff000000ff0000L) >> 8;
341 unsigned long a51 = (a & 0xff000000ff000000L) >> 24;
342 unsigned long b51 = (b & 0xff000000ff000000L) >> 24;
344 a = (a84 | a73 | a62 | a51);
345 b = (b84 | b73 | b62 | b51);
346 #endif
348 ACE_UINT32 c1 = static_cast<ACE_UINT32> (a >> 32);
349 ACE_UINT32 c2 = static_cast<ACE_UINT32> (a & 0xffffffff);
350 ACE_UINT32 c3 = static_cast<ACE_UINT32> (b >> 32);
351 ACE_UINT32 c4 = static_cast<ACE_UINT32> (b & 0xffffffff);
353 #if defined (ACE_LITTLE_ENDIAN)
354 * reinterpret_cast<ACE_UINT32*> (target + 0) = c2;
355 * reinterpret_cast<ACE_UINT32*> (target + 4) = c1;
356 * reinterpret_cast<ACE_UINT32*> (target + 8) = c4;
357 * reinterpret_cast<ACE_UINT32*> (target + 12) = c3;
358 #else
359 * reinterpret_cast<ACE_UINT32*> (target + 0) = c1;
360 * reinterpret_cast<ACE_UINT32*> (target + 4) = c2;
361 * reinterpret_cast<ACE_UINT32*> (target + 8) = c3;
362 * reinterpret_cast<ACE_UINT32*> (target + 12) = c4;
363 #endif
364 orig += 16;
365 target += 16;
369 #else /* ACE_SIZEOF_LONG != 8 */
371 while (orig < end)
373 #if defined (ACE_HAS_PENTIUM) && defined (__GNUG__)
374 unsigned int a = *reinterpret_cast<const unsigned int*> (orig);
375 unsigned int b = *reinterpret_cast<const unsigned int*> (orig + 4);
376 unsigned int c = *reinterpret_cast<const unsigned int*> (orig + 8);
377 unsigned int d = *reinterpret_cast<const unsigned int*> (orig + 12);
379 asm ("bswap %1" : "=r" (a) : "0" (a));
380 asm ("bswap %1" : "=r" (b) : "0" (b));
381 asm ("bswap %1" : "=r" (c) : "0" (c));
382 asm ("bswap %1" : "=r" (d) : "0" (d));
384 *reinterpret_cast<unsigned int*> (target) = a;
385 *reinterpret_cast<unsigned int*> (target + 4) = b;
386 *reinterpret_cast<unsigned int*> (target + 8) = c;
387 *reinterpret_cast<unsigned int*> (target + 12) = d;
388 #elif defined (ACE_HAS_PENTIUM) \
389 && (defined (_MSC_VER) || defined (__BORLANDC__)) \
390 && !defined (ACE_LACKS_INLINE_ASSEMBLY)
391 __asm mov eax, orig
392 __asm mov esi, target
393 __asm mov edx, [eax]
394 __asm mov ecx, 4[eax]
395 __asm mov ebx, 8[eax]
396 __asm mov eax, 12[eax]
397 __asm bswap edx
398 __asm bswap ecx
399 __asm bswap ebx
400 __asm bswap eax
401 __asm mov [esi], edx
402 __asm mov 4[esi], ecx
403 __asm mov 8[esi], ebx
404 __asm mov 12[esi], eax
405 #else
406 ACE_UINT32 a = * reinterpret_cast<const ACE_UINT32*> (orig);
407 ACE_UINT32 b = * reinterpret_cast<const ACE_UINT32*> (orig + 4);
408 ACE_UINT32 c = * reinterpret_cast<const ACE_UINT32*> (orig + 8);
409 ACE_UINT32 d = * reinterpret_cast<const ACE_UINT32*> (orig + 12);
411 // Expect the optimizer reordering this A LOT.
412 // We leave it this way for clarity.
413 a = (a << 24) | ((a & 0xff00) << 8) | ((a & 0xff0000) >> 8) | (a >> 24);
414 b = (b << 24) | ((b & 0xff00) << 8) | ((b & 0xff0000) >> 8) | (b >> 24);
415 c = (c << 24) | ((c & 0xff00) << 8) | ((c & 0xff0000) >> 8) | (c >> 24);
416 d = (d << 24) | ((d & 0xff00) << 8) | ((d & 0xff0000) >> 8) | (d >> 24);
418 * reinterpret_cast<ACE_UINT32*> (target) = a;
419 * reinterpret_cast<ACE_UINT32*> (target + 4) = b;
420 * reinterpret_cast<ACE_UINT32*> (target + 8) = c;
421 * reinterpret_cast<ACE_UINT32*> (target + 12) = d;
422 #endif
424 orig += 16;
425 target += 16;
428 #endif /* ACE_SIZEOF_LONG == 8 */
430 // (n & 3) == (n % 4).
431 switch (n & 3) {
432 case 3:
433 ACE_CDR::swap_4 (orig, target);
434 orig += 4;
435 target += 4;
436 ACE_FALLTHROUGH;
437 case 2:
438 ACE_CDR::swap_4 (orig, target);
439 orig += 4;
440 target += 4;
441 ACE_FALLTHROUGH;
442 case 1:
443 ACE_CDR::swap_4 (orig, target);
448 // We don't benefit from unrolling in swap_8_array and swap_16_array
449 // (swap_8 and swap_16 are big enough).
451 void
452 ACE_CDR::swap_8_array (char const * orig, char* target, size_t n)
454 // ACE_ASSERT(n > 0); The caller checks that n > 0
456 char const * const end = orig + 8*n;
457 while (orig < end)
459 swap_8 (orig, target);
460 orig += 8;
461 target += 8;
465 void
466 ACE_CDR::swap_16_array (char const * orig, char* target, size_t n)
468 // ACE_ASSERT(n > 0); The caller checks that n > 0
470 char const * const end = orig + 16*n;
471 while (orig < end)
473 swap_16 (orig, target);
474 orig += 16;
475 target += 16;
479 void
480 ACE_CDR::mb_align (ACE_Message_Block *mb)
482 #if !defined (ACE_CDR_IGNORE_ALIGNMENT)
483 char * const start = ACE_ptr_align_binary (mb->base (),
484 ACE_CDR::MAX_ALIGNMENT);
485 #else
486 char * const start = mb->base ();
487 #endif /* ACE_CDR_IGNORE_ALIGNMENT */
488 mb->rd_ptr (start);
489 mb->wr_ptr (start);
493 ACE_CDR::grow (ACE_Message_Block *mb, size_t minsize)
495 size_t newsize =
496 ACE_CDR::first_size (minsize + ACE_CDR::MAX_ALIGNMENT);
498 if (newsize <= mb->size ())
499 return 0;
501 ACE_Data_Block *db =
502 mb->data_block ()->clone_nocopy (0, newsize);
504 if (db == 0)
505 return -1;
507 // Do the equivalent of ACE_CDR::mb_align() here to avoid having
508 // to allocate an ACE_Message_Block on the stack thereby avoiding
509 // the manipulation of the data blocks reference count
510 size_t mb_len = mb->length ();
511 char *start = ACE_ptr_align_binary (db->base (),
512 ACE_CDR::MAX_ALIGNMENT);
514 ACE_OS::memcpy (start, mb->rd_ptr (), mb_len);
515 mb->data_block (db);
517 // Setting the data block on the mb resets the read and write
518 // pointers back to the beginning. We must set the rd_ptr to the
519 // aligned start and adjust the write pointer to the end
520 mb->rd_ptr (start);
521 mb->wr_ptr (start + mb_len);
523 // Remove the DONT_DELETE flags from mb
524 mb->clr_self_flags (ACE_Message_Block::DONT_DELETE);
526 return 0;
529 size_t
530 ACE_CDR::total_length (const ACE_Message_Block* begin,
531 const ACE_Message_Block* end)
533 size_t l = 0;
534 // Compute the total size.
535 for (const ACE_Message_Block *i = begin;
536 i != end;
537 i = i->cont ())
538 l += i->length ();
539 return l;
543 ACE_CDR::consolidate (ACE_Message_Block *dst,
544 const ACE_Message_Block *src)
546 if (src == 0)
547 return 0;
549 size_t const newsize =
550 ACE_CDR::first_size (ACE_CDR::total_length (src, 0)
551 + ACE_CDR::MAX_ALIGNMENT);
553 if (dst->size (newsize) == -1)
554 return -1;
556 #if !defined (ACE_CDR_IGNORE_ALIGNMENT)
557 // We must copy the contents of src into the new buffer, but
558 // respecting the alignment.
559 ptrdiff_t srcalign =
560 ptrdiff_t(src->rd_ptr ()) % ACE_CDR::MAX_ALIGNMENT;
561 ptrdiff_t dstalign =
562 ptrdiff_t(dst->rd_ptr ()) % ACE_CDR::MAX_ALIGNMENT;
563 ptrdiff_t offset = srcalign - dstalign;
564 if (offset < 0)
565 offset += ACE_CDR::MAX_ALIGNMENT;
566 dst->rd_ptr (static_cast<size_t> (offset));
567 dst->wr_ptr (dst->rd_ptr ());
568 #endif /* ACE_CDR_IGNORE_ALIGNMENT */
570 for (const ACE_Message_Block* i = src;
571 i != 0;
572 i = i->cont ())
574 // If the destination and source are the same, do not
575 // attempt to copy the data. Just update the write pointer.
576 if (dst->wr_ptr () != i->rd_ptr ())
577 dst->copy (i->rd_ptr (), i->length ());
578 else
579 dst->wr_ptr (i->length ());
581 return 0;
584 #if defined (NONNATIVE_LONGDOUBLE)
585 ACE_CDR::LongDouble&
586 ACE_CDR::LongDouble::assign (const ACE_CDR::LongDouble::NativeImpl& rhs)
588 ACE_OS::memset (this->ld, 0, sizeof (this->ld));
590 if (sizeof (rhs) == 8)
592 #if defined (ACE_LITTLE_ENDIAN)
593 static const size_t byte_zero = 1;
594 static const size_t byte_one = 0;
595 char rhs_ptr[16];
596 ACE_CDR::swap_8 (reinterpret_cast<const char*> (&rhs), rhs_ptr);
597 #else
598 static const size_t byte_zero = 0;
599 static const size_t byte_one = 1;
600 const char* rhs_ptr = reinterpret_cast<const char*> (&rhs);
601 #endif
602 ACE_INT16 sign = static_cast<ACE_INT16> (
603 static_cast<signed char> (rhs_ptr[0])) & 0x8000;
604 ACE_INT16 exponent = ((rhs_ptr[0] & 0x7f) << 4) |
605 ((rhs_ptr[1] >> 4) & 0xf);
606 const char* exp_ptr = reinterpret_cast<const char*> (&exponent);
608 // Infinity and NaN have an exponent of 0x7ff in 64-bit IEEE
609 if (exponent == 0x7ff)
611 exponent = 0x7fff;
613 else if (exponent) // exponent 0 stays 0 in 128-bit
615 exponent = (exponent - max_eleven_bit) + max_fifteen_bit;
617 exponent |= sign;
619 // Store the sign bit and exponent
620 this->ld[0] = exp_ptr[byte_zero];
621 this->ld[1] = exp_ptr[byte_one];
623 // Store the mantissa. In an 8 byte double, it is split by
624 // 4 bits (because of the 12 bits for sign and exponent), so
625 // we have to shift and or the rhs to get the right bytes.
626 size_t li = 2;
627 bool direction = true;
628 for (size_t ri = 1; ri < sizeof (rhs);)
630 if (direction)
632 this->ld[li] |= ((rhs_ptr[ri] << 4) & 0xf0);
633 direction = false;
634 ++ri;
636 else
638 this->ld[li] |= ((rhs_ptr[ri] >> 4) & 0xf);
639 direction = true;
640 ++li;
643 #if defined (ACE_LITTLE_ENDIAN)
644 ACE_OS::memcpy (rhs_ptr, this->ld, sizeof (this->ld));
645 ACE_CDR::swap_16 (rhs_ptr, this->ld);
646 #endif
648 else
650 ACE_OS::memcpy(this->ld,
651 reinterpret_cast<const char*> (&rhs), sizeof (rhs));
653 return *this;
656 ACE_CDR::LongDouble&
657 ACE_CDR::LongDouble::assign (const ACE_CDR::LongDouble& rhs)
659 if (this != &rhs)
660 *this = rhs;
661 return *this;
664 bool
665 ACE_CDR::LongDouble::operator== (const ACE_CDR::LongDouble &rhs) const
667 return ACE_OS::memcmp (this->ld, rhs.ld, 16) == 0;
670 bool
671 ACE_CDR::LongDouble::operator!= (const ACE_CDR::LongDouble &rhs) const
673 return ACE_OS::memcmp (this->ld, rhs.ld, 16) != 0;
676 ACE_CDR::LongDouble::operator ACE_CDR::LongDouble::NativeImpl () const
678 ACE_CDR::LongDouble::NativeImpl ret = 0.0;
679 char* lhs_ptr = reinterpret_cast<char*> (&ret);
681 if (sizeof (ret) == 8)
683 #if defined (ACE_LITTLE_ENDIAN)
684 static const size_t byte_zero = 1;
685 static const size_t byte_one = 0;
686 char copy[16];
687 ACE_CDR::swap_16 (this->ld, copy);
688 #else
689 static const size_t byte_zero = 0;
690 static const size_t byte_one = 1;
691 const char* copy = this->ld;
692 #endif
693 ACE_INT16 exponent = 0;
694 char* exp_ptr = reinterpret_cast<char*> (&exponent);
695 exp_ptr[byte_zero] = copy[0];
696 exp_ptr[byte_one] = copy[1];
698 ACE_INT16 sign = (exponent & 0x8000);
699 exponent &= 0x7fff;
701 // Infinity and NaN have an exponent of 0x7fff in 128-bit IEEE
702 if (exponent == 0x7fff)
704 exponent = 0x7ff;
706 else if (exponent) // exponent 0 stays 0 in 64-bit
708 exponent = (exponent - max_fifteen_bit) + max_eleven_bit;
710 exponent = (exponent << 4) | sign;
712 // Store the sign and exponent
713 lhs_ptr[0] = exp_ptr[byte_zero];
714 lhs_ptr[1] = exp_ptr[byte_one];
716 // Store the mantissa. In an 8 byte double, it is split by
717 // 4 bits (because of the 12 bits for sign and exponent), so
718 // we have to shift and or the rhs to get the right bytes.
719 size_t li = 1;
720 bool direction = true;
721 for (size_t ri = 2; li < sizeof (ret);) {
722 if (direction)
724 lhs_ptr[li] |= ((copy[ri] >> 4) & 0xf);
725 direction = false;
726 ++li;
728 else
730 lhs_ptr[li] |= ((copy[ri] & 0xf) << 4);
731 direction = true;
732 ++ri;
736 #if defined (ACE_LITTLE_ENDIAN)
737 ACE_CDR::swap_8 (lhs_ptr, lhs_ptr);
738 #endif
740 else
742 ACE_OS::memcpy(lhs_ptr, this->ld, sizeof (ret));
745 // This bit of code is unnecessary. However, this code is
746 // necessary to work around a bug in the gcc 4.1.1 optimizer.
747 ACE_CDR::LongDouble tmp;
748 tmp.assign (ret);
750 return ret;
752 #endif /* NONNATIVE_LONGDOUBLE */
755 // ACE_CDR::Fixed
757 ACE_CDR::Fixed ACE_CDR::Fixed::from_integer (ACE_CDR::LongLong val)
759 Fixed f;
760 f.value_[15] = (val < 0) ? NEGATIVE : POSITIVE;
761 f.digits_ = 0;
762 f.scale_ = 0;
763 bool high = true;
764 int idx = 15;
765 while (true)
767 const int mod = static_cast<int> (val % 10);
768 const unsigned int digit = (mod < 0) ? -mod : mod;
769 if (high)
770 f.value_[idx--] |= digit << 4;
771 else
772 f.value_[idx] = digit;
773 high = !high;
774 ++f.digits_;
775 if (val >= 10 || val <= -10)
776 val /= 10;
777 else
778 break;
781 ACE_OS::memset (f.value_, 0, idx + !high);
782 return f;
785 ACE_CDR::Fixed ACE_CDR::Fixed::from_integer (ACE_CDR::ULongLong val)
787 Fixed f;
788 f.value_[15] = POSITIVE;
789 f.digits_ = 0;
790 f.scale_ = 0;
791 bool high = true;
792 int idx = 15;
793 while (true)
795 const unsigned int digit = val % 10;
796 if (high)
797 f.value_[idx--] |= digit << 4;
798 else
799 f.value_[idx] = digit;
800 high = !high;
801 ++f.digits_;
802 if (val >= 10)
803 val /= 10;
804 else
805 break;
808 ACE_OS::memset (f.value_, 0, idx + !high);
809 return f;
812 ACE_CDR::Fixed ACE_CDR::Fixed::from_floating (LongDouble val)
814 #if defined ACE_VXWORKS && !defined __RTP__
815 typedef double BigFloat;
816 #elif defined NONNATIVE_LONGDOUBLE
817 typedef LongDouble::NativeImpl BigFloat;
818 #else
819 using BigFloat = LongDouble;
820 #endif
822 Fixed f;
823 f.digits_ = f.scale_ = 0;
824 bool negative = false;
825 if (val < 0)
827 val *= -1;
828 negative = true;
831 // How many digits are to the left of the decimal point?
832 const size_t digits_left =
833 static_cast<size_t> (1 + ((val > 0) ? std::log10 (val) : 0));
834 if (digits_left > MAX_DIGITS)
836 ACE_OS::memset (f.value_, 0, sizeof f.value_);
837 return f;
840 f.digits_ = MAX_DIGITS;
841 f.scale_ = 0;
842 BigFloat int_part;
843 BigFloat frac_part = std::modf (val, &int_part);
845 // Insert the integer part from least to most significant
846 int idx = (static_cast<int> (digits_left) + 1) / 2 - 1;
847 bool high = digits_left % 2;
848 if (idx >= 0)
849 f.value_[idx] = 0;
850 for (size_t i = 0; i < digits_left; ++i, high = !high)
852 const Octet digit = static_cast<Octet> (std::fmod (int_part, 10));
853 if (high)
854 f.value_[idx--] |= digit << 4;
855 else
856 f.value_[idx] = digit;
857 int_part /= 10;
860 // Insert the fractional part from most to least significant
861 idx = static_cast<int> (digits_left / 2);
862 high = digits_left % 2 == 0;
863 for (size_t i = digits_left; i < MAX_DIGITS; ++i, high = !high)
865 frac_part *= 10;
866 const Octet digit = static_cast<Octet> (frac_part);
867 frac_part -= digit;
868 if (high)
869 f.value_[idx] = digit << 4;
870 else
871 f.value_[idx++] |= digit;
874 if (frac_part >= 0.5)
875 ++f; // scale set after here so that ++ applies to the fractional part
877 f.scale_ = static_cast<Octet> (MAX_DIGITS - digits_left);
878 f.normalize ();
879 f.value_[15] |= negative ? NEGATIVE : POSITIVE;
880 return f;
883 void ACE_CDR::Fixed::normalize (UShort min_scale)
885 if (this->value_[15] & 0xf0 || !this->scale_)
886 return;
888 // Calculate the number of nibbles that can be moved.
889 ACE_CDR::Octet nibbles = 0;
890 while (this->digit(nibbles) == 0 && this->scale_ - nibbles > min_scale)
891 ++nibbles;
893 // Move and clear the nibbles.
894 for (ACE_CDR::Octet idx = nibbles; idx != this->digits_; ++idx) {
895 this->digit (idx - nibbles, this->digit (idx));
896 this->digit (idx, 0);
899 this->scale_ -= nibbles;
900 this->digits_ -= nibbles;
903 ACE_CDR::Fixed ACE_CDR::Fixed::from_string (const char *str)
905 const bool negative = *str == '-';
906 if (negative || *str == '+')
907 ++str;
909 const size_t span = ACE_OS::strspn (str, ".0123456789");
911 Fixed f;
912 f.value_[15] = negative ? NEGATIVE : POSITIVE;
913 f.digits_ = 0;
914 f.scale_ = 0;
916 int idx = 15;
917 bool high = true;
918 for (size_t iter = span; iter && f.digits_ < MAX_DIGITS; --iter, high = !high)
920 if (str[iter - 1] == '.')
922 f.scale_ = static_cast<Octet> (span - iter);
923 if (--iter == 0)
924 break; // skip '.'
927 const unsigned int digit = str[iter - 1] - '0';
928 if (high)
929 f.value_[idx--] |= digit << 4;
930 else
931 f.value_[idx] = digit;
932 ++f.digits_;
935 if (!f.scale_ && span > f.digits_ && str[span - f.digits_ - 1] == '.')
936 f.scale_ = f.digits_;
938 if (idx >= 0)
939 ACE_OS::memset (f.value_, 0, idx + !high);
940 return f;
943 ACE_CDR::Fixed ACE_CDR::Fixed::from_octets (const Octet *array, int len,
944 unsigned int scale)
946 Fixed f;
947 ACE_OS::memcpy (f.value_ + 16 - len, array, len);
948 ACE_OS::memset (f.value_, 0, 16 - len);
949 f.scale_ = scale;
951 f.digits_ = len * 2 - 1;
952 if (len > 1 && (array[0] >> 4) == 0)
953 --f.digits_;
955 return f;
958 ACE_CDR::Fixed::operator ACE_CDR::LongLong () const
960 LongLong val (0);
962 for (int i = this->digits_ - 1; i >= this->scale_; --i)
963 val = 10 * val + this->digit (i);
965 if (this->sign ())
966 val *= -1;
968 return val;
971 ACE_CDR::Fixed::operator ACE_CDR::LongDouble () const
973 LongDouble val = ACE_CDR_LONG_DOUBLE_INITIALIZER;
975 for (int i = this->digits_ - 1; i >= this->scale_; --i)
976 ACE_CDR_LONG_DOUBLE_ASSIGNMENT (val, 10 * val + this->digit (i));
978 for (int i = this->scale_ - 1; i >= 0; --i)
979 val += this->digit (i) * std::pow (10.0l, i - this->scale_);
981 if (this->sign ())
982 val *= -1;
984 return val;
987 ACE_CDR::Fixed ACE_CDR::Fixed::round (UShort scale) const
989 Fixed f = *this;
990 if (scale < f.scale_)
992 for (UShort i = 0; i < f.scale_ - scale; ++i)
993 f.digit (i, 0);
994 f.normalize (scale);
995 const bool negative = f.sign ();
996 if (negative)
997 f.value_[15] = (f.value_[15] & 0xf0) | POSITIVE;
998 if (this->digit (this->scale_ - scale - 1) >= 5)
1000 f.scale_ = 0;
1001 ++f;
1002 f.scale_ = static_cast<Octet> (scale);
1004 if (negative && !!f)
1005 f.value_[15] = (f.value_[15] & 0xf0) | NEGATIVE;
1007 return f;
1010 ACE_CDR::Fixed ACE_CDR::Fixed::truncate (UShort scale) const
1012 Fixed f = *this;
1013 if (scale < f.scale_)
1015 for (UShort i = 0; i < f.scale_ - scale; ++i)
1016 f.digit (i, 0);
1017 f.normalize (scale);
1018 if (f.sign ())
1020 f.value_[15] = (f.value_[15] & 0xf0) | POSITIVE;
1021 if (!!f)
1022 f.value_[15] = (f.value_[15] & 0xf0) | NEGATIVE;
1025 return f;
1028 namespace {
1029 struct BufferAppender
1031 BufferAppender (char *buffer, size_t buffer_size)
1032 : buffer_ (buffer), buffer_size_ (buffer_size), idx_ (0) {}
1034 bool operator+= (char ch)
1036 if (this->idx_ == this->buffer_size_ - 1)
1037 return false;
1038 this->buffer_[this->idx_++] = ch;
1039 return true;
1042 char *const buffer_;
1043 const size_t buffer_size_;
1044 size_t idx_;
1048 bool ACE_CDR::Fixed::to_string (char *buffer, size_t buffer_size) const
1050 if (!buffer || buffer_size < 2)
1051 return false;
1053 const bool negative = this->sign ();
1054 if (negative)
1055 *buffer = '-';
1056 BufferAppender ba (buffer + negative, buffer_size - negative);
1058 for (int i = 15 - this->digits_ / 2; i < 16; ++i)
1060 const Octet high = this->value_[i] >> 4, low = this->value_[i] & 0xf;
1062 if ((15 - i) * 2 != this->digits_)
1064 if (this->scale_ == 1 + 2 * (15 - i))
1066 if (!ba.idx_ && !(ba += '0'))
1067 return false;
1069 if (!(ba += '.'))
1070 return false;
1073 if ((ba.idx_ || high) && !(ba += '0' + high))
1074 return false;
1077 if (this->scale_ && this->scale_ == 2 * (15 - i))
1079 if (!ba.idx_ && !(ba += '0'))
1080 return false;
1082 if (!(ba += '.'))
1083 return false;
1086 if (i < 15 && (ba.idx_ || low) && !(ba += '0' + low))
1087 return false;
1090 if (!ba.idx_ && !(ba += '0'))
1091 return false;
1093 buffer[ba.idx_ + negative] = 0;
1094 return true;
1097 const ACE_CDR::Octet *ACE_CDR::Fixed::to_octets (int &n) const
1099 n = (this->digits_ + 2) / 2;
1100 return 16 - n + reinterpret_cast<const Octet *> (this->value_);
1103 ACE_CDR::Fixed::ConstIterator ACE_CDR::Fixed::pre_add (const ACE_CDR::Fixed &f)
1105 ConstIterator rhs_iter = f.begin ();
1106 if (f.scale_ > this->scale_)
1108 const int scale_diff = f.scale_ - this->scale_;
1109 rhs_iter += scale_diff - this->lshift (scale_diff);
1112 if (f.digits_ - f.scale_ > this->digits_ - this->scale_)
1114 ACE_CDR::Octet new_digits = this->digits_ + (f.digits_ - f.scale_) - (this->digits_ - this->scale_);
1115 if (new_digits > MAX_DIGITS)
1117 for (size_t i = 0; i < static_cast<size_t> (new_digits - MAX_DIGITS); ++i)
1118 this->digit (static_cast<int> (i), 0);
1119 this->normalize (this->scale_ - (new_digits - MAX_DIGITS));
1120 this->digits_ = MAX_DIGITS;
1122 else
1123 this->digits_ = new_digits;
1125 return rhs_iter;
1128 ACE_CDR::Fixed &ACE_CDR::Fixed::operator+= (const Fixed &rhs)
1130 if (!this->sign () && rhs.sign ())
1131 return *this -= -rhs;
1133 if (this->sign () && !rhs.sign ())
1135 Fixed negated = -*this;
1136 negated -= rhs;
1137 return *this = -negated;
1140 ConstIterator rhs_iter = this->pre_add (rhs);
1142 Iterator lhs_iter = this->begin ();
1143 if (this->scale_ > rhs.scale_)
1144 lhs_iter += this->scale_ - rhs.scale_;
1146 bool carry = false;
1147 for (; rhs_iter != rhs.end (); ++lhs_iter, ++rhs_iter)
1149 const Octet digit = *lhs_iter + *rhs_iter + carry;
1150 carry = digit > 9;
1151 *lhs_iter = digit - (carry ? 10 : 0);
1154 if (carry)
1156 if (this->digits_ < MAX_DIGITS)
1158 *lhs_iter = 1;
1159 ++this->digits_;
1161 else if (this->scale_)
1163 this->digit (0, 0);
1164 this->normalize (this->scale_ - 1);
1165 this->digit (MAX_DIGITS - 1, 1);
1169 return *this;
1172 int ACE_CDR::Fixed::lshift (int digits)
1174 int bytes = 0;
1175 for (; bytes < digits / 2; ++bytes)
1176 if (this->value_[bytes])
1177 break;
1179 int shifted = 0;
1180 if ((digits % 2) && !(this->value_[bytes] & 0xf0))
1182 for (int i = 0; i < 15 - bytes; ++i)
1183 this->value_[i] = (this->value_[i + bytes] & 0xf) << 4
1184 | (this->value_[i + bytes + 1] >> 4);
1185 std::memset (this->value_ + 15 - bytes, 0, bytes);
1186 this->value_[15] &= 0xf;
1187 shifted = 2 * bytes + 1;
1189 else if (bytes)
1191 std::memmove (this->value_, this->value_ + bytes, 16 - bytes);
1192 this->value_[15] &= 0xf;
1193 std::memset (this->value_ + 16 - bytes, 0, bytes - 1);
1194 this->value_[15 - bytes] &= 0xf0;
1195 shifted = 2 * bytes;
1198 this->digits_ += shifted;
1199 if (this->digits_ > MAX_DIGITS)
1200 this->digits_ = MAX_DIGITS;
1202 this->scale_ += shifted;
1203 if (this->scale_ > MAX_DIGITS)
1204 this->scale_ = MAX_DIGITS;
1206 return shifted;
1209 ACE_CDR::Fixed &ACE_CDR::Fixed::operator-= (const Fixed &rhs)
1211 if (!this->sign () && rhs.sign ())
1212 return *this += -rhs;
1214 if (this->sign () && !rhs.sign ())
1216 Fixed negated = -*this;
1217 negated += rhs;
1218 return *this = -negated;
1221 const Fixed before = *this;
1222 ConstIterator rhs_iter = this->pre_add (rhs);
1224 Iterator lhs_iter = this->begin ();
1225 if (this->scale_ > rhs.scale_)
1226 lhs_iter += this->scale_ - rhs.scale_;
1228 bool borrow = false;
1229 for (; rhs_iter != rhs.end (); ++lhs_iter, ++rhs_iter)
1230 if (*rhs_iter + borrow <= *lhs_iter)
1232 *lhs_iter -= *rhs_iter + borrow;
1233 borrow = false;
1235 else
1237 *lhs_iter += 10 - *rhs_iter - borrow;
1238 borrow = true;
1241 while (borrow && lhs_iter != this->end ())
1242 if (*lhs_iter)
1244 --*lhs_iter;
1245 borrow = false;
1247 else
1248 *lhs_iter = 9;
1250 if (borrow)
1251 return *this = -(rhs - before);
1253 this->ltrim ();
1254 return *this;
1257 ACE_CDR::Fixed &ACE_CDR::Fixed::operator*= (const Fixed &rhs)
1259 if (!this->sign () && rhs.sign ())
1260 this->value_[15] = (this->value_[15] & 0xf0) | NEGATIVE;
1261 else if (this->sign () && rhs.sign ())
1262 this->value_[15] = (this->value_[15] & 0xf0) | POSITIVE;
1264 this->ltrim ();
1265 Fixed right = rhs;
1266 right.ltrim ();
1268 Octet temp[MAX_DIGITS * 2];
1269 int carry = 0;
1271 for (int col = 0; col < this->digits_ + right.digits_; ++col)
1273 for (int row = (std::max) (0, col - this->digits_ + 1);
1274 row < (std::min) (col + 1, int (right.digits_)); ++row)
1275 carry += this->digit (col - row) * right.digit (row);
1276 temp[col] = carry % 10;
1277 carry /= 10;
1280 this->digits_ += right.digits_;
1281 this->scale_ += right.scale_;
1282 int digit_offset = 0;
1284 if (this->digits_ > MAX_DIGITS)
1286 digit_offset = this->digits_ - MAX_DIGITS;
1287 this->digits_ = MAX_DIGITS;
1288 if (this->scale_ > digit_offset)
1289 this->scale_ -= digit_offset;
1292 for (int i = 0; i < this->digits_; ++i)
1293 this->digit (i, temp[i + digit_offset]);
1295 this->ltrim ();
1296 return *this;
1299 ACE_CDR::Fixed &ACE_CDR::Fixed::operator/= (const Fixed &rhs)
1301 if (!rhs)
1302 return *this;
1304 if (rhs.scale_ && rhs.scale_ <= this->scale_)
1305 this->scale_ -= rhs.scale_;
1306 else if (rhs.scale_)
1308 const Octet shifted = this->lshift (rhs.scale_ - this->scale_);
1309 this->scale_ -= shifted;
1312 Fixed rhs_no_scale = rhs;
1313 rhs_no_scale.scale_ = 0;
1314 rhs_no_scale.value_[15] = (rhs_no_scale.value_[15] & 0xf0) | POSITIVE;
1315 rhs_no_scale.ltrim ();
1317 this->ltrim ();
1319 if (!this->sign () && rhs.sign ())
1320 this->value_[15] = (this->value_[15] & 0xf0) | NEGATIVE;
1321 else if (this->sign () && rhs.sign ())
1322 this->value_[15] = (this->value_[15] & 0xf0) | POSITIVE;
1324 static const Fixed one = from_integer (LongLong (1)),
1325 two = from_integer (LongLong (2)),
1326 three = from_integer (LongLong (3)),
1327 five = from_integer (LongLong (5));
1329 if (rhs_no_scale == one)
1330 return *this;
1332 // Most sig digit of rhs must be >= 5
1333 switch (rhs_no_scale.digit (rhs_no_scale.digits_ - 1))
1335 case 1:
1336 return *this = (*this * five) / (rhs_no_scale * five);
1337 case 2:
1338 return *this = (*this * three) / (rhs_no_scale * three);
1339 case 3:
1340 case 4:
1341 return *this = (*this * two) / (rhs_no_scale * two);
1342 default:
1343 break;
1346 const bool neg = this->sign ();
1347 if (neg)
1348 this->value_[15] = (this->value_[15] & 0xf0) | POSITIVE;
1350 Fixed r;
1351 Fixed q = this->div_helper2 (rhs_no_scale, r);
1352 q.scale_ = this->scale_;
1354 if (!r) {
1355 *this = neg ? -q : q;
1356 this->normalize ();
1357 return *this;
1360 const int shift = q.lshift (MAX_DIGITS);
1361 if (shift)
1363 const Octet scale = r.lshift (shift);
1364 r.scale_ = 0;
1365 Fixed r2;
1366 r = r.div_helper2 (rhs_no_scale, r2);
1367 r.scale_ = scale;
1368 q += r;
1371 *this = neg ? -q : q;
1372 this->normalize ();
1373 return *this;
1376 ACE_CDR::Fixed ACE_CDR::Fixed::div_helper2 (const Fixed &rhs, Fixed &r) const
1378 if (this->digits_ < rhs.digits_)
1379 r = *this;
1380 else if (this->digits_ == rhs.digits_)
1381 if (*this < rhs)
1382 r = *this;
1383 else
1385 r = *this - rhs;
1386 return from_integer (LongLong (1));
1388 else if (this->digits_ == rhs.digits_ + 1)
1389 return this->div_helper1 (rhs, r);
1390 else
1392 const int dig = this->digits_ - rhs.digits_ - 1;
1393 Fixed top = *this, bot = *this; // split with bot having dig digits
1394 for (int i = 0; i < dig; ++i)
1395 top.digit (i, 0);
1396 for (int i = dig; i < this->digits_; ++i)
1397 bot.digit (i, 0);
1398 bot.digits_ = dig;
1399 top.scale_ += dig;
1400 top.normalize (this->scale_);
1402 Fixed rtop;
1403 const Fixed qtop = top.div_helper1 (rhs, rtop);
1404 const Fixed qbot = rtop.join (dig, bot).div_helper2 (rhs, r);
1405 return qtop.join (dig, qbot);
1408 return from_integer ();
1411 ACE_CDR::Fixed ACE_CDR::Fixed::div_helper1 (const Fixed &rhs, Fixed &r) const
1413 static const Fixed ten = from_integer (LongLong (10));
1414 if (*this >= rhs * ten)
1415 return ten + (*this - rhs * ten).div_helper1 (rhs, r);
1417 int q = (this->digit (this->digits_ - 1) * 10 +
1418 this->digit (this->digits_ - 2)) / rhs.digit (rhs.digits_ - 1);
1419 if (q > 9)
1420 q = 9;
1421 Fixed t = from_integer (LongLong (q)) * rhs;
1422 t.scale_ = this->scale_;
1423 for (int i = 0; i < 2 && t > *this; ++i)
1425 --q;
1426 t -= rhs;
1429 r = *this - t;
1430 return from_integer (LongLong (q));
1433 ACE_CDR::Fixed ACE_CDR::Fixed::join (int digits, const Fixed &bot) const
1435 Fixed res = bot;
1436 res.digits_ = this->digits_ + digits;
1437 for (int i = digits; i < MAX_DIGITS && i - digits < this->digits_; ++i)
1438 res.digit (i, this->digit (i - digits));
1439 return res;
1442 ACE_CDR::Fixed &ACE_CDR::Fixed::operator++ ()
1444 if (this->sign ())
1446 this->value_[15] = (this->value_[15] & 0xf0) | POSITIVE;
1447 if (!!--*this) // decrement and check if result is nonzero
1448 this->value_[15] = (this->value_[15] & 0xf0) | NEGATIVE;
1450 else
1452 Iterator iter = this->begin ();
1453 iter += this->scale_;
1454 for (; iter != this->end (); ++iter)
1456 if (*iter < 9)
1458 ++*iter;
1459 return *this;
1461 *iter = 0;
1463 if (this->digits_ < MAX_DIGITS)
1465 ++this->digits_;
1466 *iter = 1;
1469 return *this;
1472 ACE_CDR::Fixed &ACE_CDR::Fixed::operator-- ()
1474 if (this->sign ())
1476 this->value_[15] = (this->value_[15] & 0xf0) | POSITIVE;
1477 ++*this;
1478 this->value_[15] = (this->value_[15] & 0xf0) | NEGATIVE;
1480 else
1482 Fixed before = *this;
1483 Iterator iter = this->begin ();
1484 iter += this->scale_;
1485 for (; iter != this->end (); ++iter)
1487 if (*iter)
1489 --*iter;
1490 return *this;
1492 *iter = 9;
1494 *this = before - from_integer (ULongLong (1));
1496 return *this;
1499 bool ACE_CDR::Fixed::operator! () const
1501 static const Octet ZERO[] = {0, 0, 0, 0, 0, 0, 0, 0,
1502 0, 0, 0, 0, 0, 0, 0, POSITIVE};
1503 return 0 == ACE_OS::memcmp (this->value_, ZERO, sizeof ZERO);
1506 ACE_OSTREAM_TYPE &operator<< (ACE_OSTREAM_TYPE &lhs, const ACE_CDR::Fixed &rhs)
1508 char digits[ACE_CDR::Fixed::MAX_STRING_SIZE];
1509 rhs.to_string (digits, sizeof digits);
1511 #ifdef ACE_LACKS_IOSTREAM_TOTALLY
1512 ACE_OS::fputs (digits, &lhs);
1513 #else
1514 lhs << digits;
1515 #endif
1516 return lhs;
1519 #ifndef ACE_LACKS_IOSTREAM_TOTALLY
1520 std::istream &operator>> (std::istream &lhs, ACE_CDR::Fixed &rhs)
1522 double num;
1523 lhs >> num;
1524 ACE_CDR::LongDouble ld;
1525 ACE_CDR_LONG_DOUBLE_ASSIGNMENT (ld, num);
1526 rhs = ACE_CDR::Fixed::from_floating (ld);
1527 return lhs;
1529 #endif
1531 bool ACE_CDR::Fixed::less (const ACE_CDR::Fixed &rhs) const
1533 const Fixed &lhs = *this;
1534 if (lhs.sign () != rhs.sign ())
1535 return lhs.sign ();
1537 // signs of lhs and rhs are the same so lhs < rhs reduces to:
1538 // if positive, |lhs| < |rhs|
1539 // if negative, |rhs| < |lhs|
1540 // 'a' will refer to the value left of < and 'b' to the value to the right
1541 const ACE_CDR::Fixed &a = lhs.sign () ? rhs : lhs,
1542 &b = lhs.sign () ? lhs : rhs;
1544 if (a.scale_ == b.scale_)
1545 return ACE_OS::memcmp (a.value_, b.value_, sizeof a.value_) < 0;
1547 const int a_int_dig = a.digits_ - a.scale_, b_int_dig = b.digits_ - b.scale_;
1549 if (a_int_dig > b_int_dig)
1551 for (int i = 1; i <= a_int_dig - b_int_dig; ++i)
1552 if (a.digit (a.digits_ - i))
1553 return false;
1555 else if (a_int_dig < b_int_dig)
1557 for (int i = 1; i <= b_int_dig - a_int_dig; ++i)
1558 if (b.digit (b.digits_ - i))
1559 return true;
1562 const int common_frac = (std::min) (a.scale_, b.scale_),
1563 common_dig = (std::min) (a_int_dig, b_int_dig) + common_frac,
1564 a_off = a.scale_ - common_frac, // a's offset (more scale than b)
1565 b_off = b.scale_ - common_frac; // b's offset (more scale than a)
1567 for (int i = 1; i <= common_dig; ++i)
1568 if (a.digit (a_off + common_dig - i) < b.digit (b_off + common_dig - i))
1569 return true;
1571 for (int i = 1; i <= a_off; ++i)
1572 if (a.digit (a_off - i))
1573 return false;
1575 for (int i = 1; i <= b_off; ++i)
1576 if (b.digit (b_off - i))
1577 return true;
1579 return false;
1582 bool ACE_CDR::Fixed::equal (const ACE_CDR::Fixed &rhs) const
1584 const Fixed &lhs = *this;
1585 if (lhs.sign () != rhs.sign ())
1586 return false;
1588 if (lhs.scale_ == rhs.scale_)
1589 return 0 == ACE_OS::memcmp (lhs.value_, rhs.value_, sizeof lhs.value_);
1591 const ACE_CDR::Fixed &more = (lhs.scale_ > rhs.scale_) ? lhs : rhs,
1592 &fewer = (lhs.scale_ > rhs.scale_) ? rhs : lhs;
1594 const ACE_CDR::Octet scale_diff = more.scale_ - fewer.scale_;
1596 ACE_CDR::Fixed::ConstIterator more_iter = more.begin (),
1597 more_end = more.end ();
1599 for (ACE_CDR::Octet i = 0; i < scale_diff; ++i)
1600 if (more_iter == more_end || *more_iter++)
1601 return false; // digits in more that are missing in fewer must be 0
1603 ACE_CDR::Fixed::ConstIterator fewer_iter = fewer.begin (),
1604 fewer_end = fewer.end ();
1606 while (more_iter != more_end && fewer_iter != fewer_end)
1607 if (*more_iter++ != *fewer_iter++)
1608 return false; // digits in common must match
1610 while (more_iter != more_end)
1611 if (*more_iter++)
1612 return false; // extra (more significant) digits in more must be 0
1614 while (fewer_iter != fewer_end)
1615 if (*fewer_iter++)
1616 return false; // extra (more significant) digits in fewer must be 0
1618 return true;
1621 ACE_END_VERSIONED_NAMESPACE_DECL