InDesign SDK  20.5
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
PMReal.h
1 //========================================================================================
2 //
3 // $File$
4 //
5 // Owner: jargast
6 //
7 // $Author$
8 //
9 // $DateTime$
10 //
11 // $Revision$
12 //
13 // $Change$
14 //
15 // Copyright 1997-2010 Adobe Systems Incorporated. All rights reserved.
16 //
17 // NOTICE: Adobe permits you to use, modify, and distribute this file in accordance
18 // with the terms of the Adobe license agreement accompanying it. If you have received
19 // this file from a source other than Adobe, then your use, modification, or
20 // distribution of it requires the prior written permission of Adobe.
21 //
22 //========================================================================================
23 
24 #ifndef __PMReal__
25 #define __PMReal__
26 
27 #include <math.h>
28 
29 #include "K2Assert.h"
30 
31 #ifdef WINDOWS
32 #include <stdio.h>
33 #include <float.h>
34 #endif
35 
36 #if defined(DEBUG)
37 #include <limits>
38 #endif
39 
40 
41 constexpr double kPMRealEpsilon = 1.0e-8;
42 constexpr double kPMPi = 3.141592653589793238462643383279502884197169399375105820974944;
43 constexpr double kPMMaxReal = 8.9884656743115795e+307;
44 
45 
46 // NOTE: Code Generation 7/24/96
47 //
48 // MSFT VC is quite good at inlining things and produces code nearly
49 // identical to using doubles.
50 //
51 // MW's shipping compiler is not as good -- it seems to only inline
52 // one level deep so that an inline containing an inline is never
53 // expanded. There are other compiler back ends for MW that we could
54 // try.
55 
56 
57 
58 
87 class PMReal
88 {
89 // ----- Constructors/destructors
90 public:
91  typedef base_type data_type;
92 
96  constexpr PMReal() noexcept : fRealValue(0.0)
97  {
98  }
99 
105  constexpr PMReal(const PMReal& ) noexcept = default;
106  constexpr PMReal(PMReal&&) noexcept = default;
107 
113  constexpr PMReal(double d) noexcept : fRealValue(d)
114  {
115  }
116 
124  friend PMReal ToPMReal(Fixed fx);
125 
126  // PMREALCLEANUP
127  //operator double() { return fRealValue; }
128  //operator const double&() const { return fRealValue; }
129 
130 // ----- Conversion operators
137  friend double ToDouble(const PMReal& r) noexcept;
138 
145  friend float ToFloat(const PMReal& r);
146 
154  friend Fixed ToFixed(const PMReal& r);
155 
164  friend int16 ToInt16(const PMReal& r);
165 
174  friend uint16 ToUInt16(const PMReal& r);
175 
184  friend int32 ToInt32(const PMReal& r);
185 
194  friend uint32 ToUInt32(const PMReal& r);
195 
196 // ----- Math operators
203  friend PMReal operator -(const PMReal& a);
204 
212  friend PMReal operator +(const PMReal& a, const PMReal& b);
213 
221  friend PMReal operator -(const PMReal& a, const PMReal& b);
222 
230  friend PMReal operator *(const PMReal& a, const PMReal& b);
231 
239  friend PMReal operator /(const PMReal& a, const PMReal& b);
240 
241 // ----- Math functions
248  friend PMReal Round(const PMReal& a);
249 
256  friend PMReal Floor(const PMReal& a);
257 
264  friend PMReal Ceiling(const PMReal& a);
265 
272  friend PMReal abs(const PMReal& a);
273 
283  friend PMReal NearestMultiple(const PMReal& a, const PMReal& factor);
284 
292  friend PMReal Mod(const PMReal& a, const PMReal& b);
293 
294 // ----- Assignment Operators
301  PMReal& operator=(const PMReal &) noexcept = default;
302  PMReal& operator=(PMReal &&) noexcept = default;
303 
310  PMReal& operator +=(const PMReal& a);
311 
318  PMReal& operator -=(const PMReal& a);
319 
326  PMReal& operator *=(const PMReal& a);
327 
334  PMReal& operator /=(const PMReal& a);
335 
336 // ----- Comparison Operators
344  friend bool16 operator ==(const PMReal& a, const PMReal& b) noexcept;
345 
353  friend bool16 operator !=(const PMReal& a, const PMReal& b) noexcept;
354 
362  friend bool16 operator <(const PMReal& a, const PMReal& b) noexcept;
363 
371  friend bool16 operator >(const PMReal& a, const PMReal& b) noexcept;
372 
381  friend bool16 operator <=(const PMReal& a, const PMReal& b) noexcept;
382 
391  friend bool16 operator >=(const PMReal& a, const PMReal& b) noexcept;
392 
403  friend bool16 AnglesEqual(const PMReal& a, const PMReal& b) noexcept;
404 
413  friend bool16 EqualsWithEpsilon(const PMReal& a, const PMReal& b, double epsilon) noexcept;
414 
415 private:
416  double fRealValue;
417 };
418 
419 
420 /*--------------------------------------------------------------------*/
421 /*--------------------------------------------------------------------*/
422 /*--------------------------------------------------------------------*/
423 
424 // Math operators
425 inline PMReal operator-(const PMReal& r)
426 {
427 #ifdef WINDOWS
428  // Verify that exception handling is what we expect.
429  ASSERT_MSG(kDefaultFPUExceptions == _controlfp(0, 0), FORMAT_ARGS("Unexpected floating point control word! You may see floating point exceptions (actual:0x%8.8X expected:0x%8.8X)",_controlfp(0, 0), kDefaultFPUExceptions));
430 #endif
431 
432  return -r.fRealValue;
433 }
434 
435 inline PMReal operator+(const PMReal& a, const PMReal& b)
436 {
437 #ifdef WINDOWS
438  // Verify that exception handling is what we expect.
439  ASSERT_MSG(kDefaultFPUExceptions == _controlfp(0, 0), FORMAT_ARGS("Unexpected floating point control word! You may see floating point exceptions (actual:0x%8.8X expected:0x%8.8X)",_controlfp(0, 0), kDefaultFPUExceptions));
440 #endif
441 
442  return a.fRealValue + b.fRealValue;
443 }
444 
445 inline PMReal operator-(const PMReal& a, const PMReal& b)
446 {
447 #ifdef WINDOWS
448  // Verify that exception handling is what we expect.
449  ASSERT_MSG(kDefaultFPUExceptions == _controlfp(0, 0), FORMAT_ARGS("Unexpected floating point control word! You may see floating point exceptions (actual:0x%8.8X expected:0x%8.8X)",_controlfp(0, 0), kDefaultFPUExceptions));
450 #endif
451 
452  return a.fRealValue - b.fRealValue;
453 }
454 
455 inline PMReal operator*(const PMReal& a, const PMReal& b)
456 {
457 #ifdef WINDOWS
458  // Verify that exception handling is what we expect.
459  ASSERT_MSG(kDefaultFPUExceptions == _controlfp(0, 0), FORMAT_ARGS("Unexpected floating point control word! You may see floating point exceptions (actual:0x%8.8X expected:0x%8.8X)",_controlfp(0, 0), kDefaultFPUExceptions));
460 #endif
461 
462  return a.fRealValue * b.fRealValue;
463 }
464 
465 inline PMReal operator/(const PMReal& a, const PMReal& b)
466 {
467 #ifdef WINDOWS
468  // Verify that exception handling is what we expect.
469  ASSERT_MSG(kDefaultFPUExceptions == _controlfp(0, 0), FORMAT_ARGS("Unexpected floating point control word! You may see floating point exceptions (actual:0x%8.8X expected:0x%8.8X)",_controlfp(0, 0), kDefaultFPUExceptions));
470 #endif
471 
472  return a.fRealValue / b.fRealValue;
473 }
474 
475 
476 // Math functions
477 inline PMReal Floor(const PMReal& a)
478 {
479  //return (a.fRealValue < 0.0 && a.fRealValue != double(int32(a.fRealValue)) ? int32(a.fRealValue - 1.0) : int32(a.fRealValue));
480  return ::floor (a.fRealValue);
481 }
482 
483 inline PMReal Ceiling(const PMReal& a)
484 {
485  return (a.fRealValue > 0.0 && a.fRealValue != double(int32(a.fRealValue)) ? int32(a.fRealValue + 1.0) : int32(a.fRealValue));
486 }
487 
488 inline PMReal Round(const PMReal& a)
489 {
490  PMReal r(a.fRealValue + 0.5);
491 
492  return ::Floor(r);
493 }
494 
495 inline PMReal abs(const PMReal& a)
496 {
497 // NOTE: Implicit construction on return
498  return ::fabs(a.fRealValue);
499 }
500 
501 inline PMReal NearestMultiple(const PMReal&a, const PMReal& factor)
502 {
503  return ::Round (a / factor) * factor;
504 }
505 
506 inline PMReal Mod(const PMReal& a, const PMReal& b)
507 {
508 // NOTE: Implicit construction on return
509  return ::fmod(a.fRealValue, b.fRealValue);
510 }
511 
512 // Conversion operators
513 inline Fixed ToFixed(const PMReal& r)
514 {
515  ASSERT(static_cast<int32>(r.fRealValue) >= kMinInt16);
516  ASSERT(static_cast<int32>(r.fRealValue) <= kMaxInt16);
517 
518  PMReal a(::Round(r * 65536.0));
519  return int32(a.fRealValue);
520 }
521 
522 inline double ToDouble (const PMReal& r) noexcept
523 {
524  return r.fRealValue;
525 }
526 
527 inline float ToFloat (const PMReal& r)
528 {
529  return (float) r.fRealValue;
530 }
531 
532 inline int16 ToInt16 (const PMReal& r)
533 {
534  ASSERT(r.fRealValue >= kMinInt16);
535  ASSERT(r.fRealValue <= kMaxInt16);
536 
537  return (int16) r.fRealValue;
538 }
539 
540 inline uint16 ToUInt16 (const PMReal& r)
541 {
542  ASSERT(r.fRealValue >= 0.0);
543  ASSERT(r.fRealValue <= kMaxUInt16);
544 
545  return (uint16) r.fRealValue;
546 }
547 
548 inline int32 ToInt32 (const PMReal& r)
549 {
550  ASSERT_MSG(r.fRealValue >= kMinInt32, FORMAT_ARGS("Value %4.4f is too small to convert to int32",r.fRealValue));
551  ASSERT_MSG(r.fRealValue <= kMaxInt32, FORMAT_ARGS("Value %4.4f is too large to convert to int32",r.fRealValue));
552 
553  return (int32) r.fRealValue;
554 }
555 
556 inline uint32 ToUInt32 (const PMReal& r)
557 {
558  ASSERT(r.fRealValue >= 0.0);
559  ASSERT(r.fRealValue <= kMaxUInt32);
560 
561  return (uint32) r.fRealValue;
562 }
563 
564 inline PMReal ToPMReal (Fixed fx)
565 {
566  // NOTE: Implicit construction on return
567  return double(fx) * 0.0000152587890625; // 1/65536
568 }
569 
571 {
572  fRealValue += a.fRealValue;
573 
574  return *this;
575 }
576 
578 {
579  fRealValue -= a.fRealValue;
580 
581  return *this;
582 }
583 
585 {
586  fRealValue *= a.fRealValue;
587 
588  return *this;
589 }
590 
592 {
593  fRealValue /= a.fRealValue;
594 
595  return *this;
596 }
597 
598 
599 // Comparison operators
600 inline bool16 operator<(const PMReal& a, const PMReal& b) noexcept
601 {
602  return a.fRealValue < (b.fRealValue - kPMRealEpsilon);
603 }
604 
605 inline bool16 operator>(const PMReal& a, const PMReal& b) noexcept
606 {
607  return a.fRealValue > (b.fRealValue + kPMRealEpsilon);
608 }
609 
610 inline bool16 operator<=(const PMReal& a, const PMReal& b) noexcept
611 {
612  return a.fRealValue <= (b.fRealValue + kPMRealEpsilon);
613 }
614 
615 inline bool16 operator>=(const PMReal& a, const PMReal& b) noexcept
616 {
617  return a.fRealValue >= (b.fRealValue - kPMRealEpsilon);
618 }
619 
620 inline bool16 operator==(const PMReal& a, const PMReal& b) noexcept
621 {
622  return ::fabs(a.fRealValue - b.fRealValue) < kPMRealEpsilon;
623 }
624 
625 inline bool16 operator!=(const PMReal& a, const PMReal& b) noexcept
626 {
627  return !(a == b);
628 }
629 
630  // allow epsilon compare with angles in degress (360 == 0)
631 inline bool16 AnglesEqual(const PMReal& a, const PMReal& b) noexcept
632 {
633  if (a == b)
634  return kTrue;
635  else if (a > b)
636  return ::fabs((a.fRealValue - 360.0) - b.fRealValue) < kPMRealEpsilon;
637  else
638  return ::fabs(a.fRealValue - (b.fRealValue - 360.0)) < kPMRealEpsilon;
639 }
640 
641 inline bool16 EqualsWithEpsilon(const PMReal& a, const PMReal& b, double epsilon) noexcept
642 {
643  return ::fabs(a.fRealValue - b.fRealValue) < epsilon;
644 }
645 #endif
646