Home | History | Annotate | Download | only in i18n
      1 /************************************************************************
      2  * Copyright (C) 1996-2008, International Business Machines Corporation *
      3  * and others. All Rights Reserved.                                     *
      4  ************************************************************************
      5  *  2003-nov-07   srl       Port from Java
      6  */
      7 
      8 #ifndef ASTRO_H
      9 #define ASTRO_H
     10 
     11 #include "unicode/utypes.h"
     12 
     13 #if !UCONFIG_NO_FORMATTING
     14 
     15 #include "gregoimp.h"  // for Math
     16 #include "unicode/unistr.h"
     17 
     18 U_NAMESPACE_BEGIN
     19 
     20 /**
     21  * <code>CalendarAstronomer</code> is a class that can perform the calculations to
     22  * determine the positions of the sun and moon, the time of sunrise and
     23  * sunset, and other astronomy-related data.  The calculations it performs
     24  * are in some cases quite complicated, and this utility class saves you
     25  * the trouble of worrying about them.
     26  * <p>
     27  * The measurement of time is a very important part of astronomy.  Because
     28  * astronomical bodies are constantly in motion, observations are only valid
     29  * at a given moment in time.  Accordingly, each <code>CalendarAstronomer</code>
     30  * object has a <code>time</code> property that determines the date
     31  * and time for which its calculations are performed.  You can set and
     32  * retrieve this property with {@link #setDate setDate}, {@link #getDate getDate}
     33  * and related methods.
     34  * <p>
     35  * Almost all of the calculations performed by this class, or by any
     36  * astronomer, are approximations to various degrees of accuracy.  The
     37  * calculations in this class are mostly modelled after those described
     38  * in the book
     39  * <a href="http://www.amazon.com/exec/obidos/ISBN=0521356997" target="_top">
     40  * Practical Astronomy With Your Calculator</a>, by Peter J.
     41  * Duffett-Smith, Cambridge University Press, 1990.  This is an excellent
     42  * book, and if you want a greater understanding of how these calculations
     43  * are performed it a very good, readable starting point.
     44  * <p>
     45  * <strong>WARNING:</strong> This class is very early in its development, and
     46  * it is highly likely that its API will change to some degree in the future.
     47  * At the moment, it basically does just enough to support {@link IslamicCalendar}
     48  * and {@link ChineseCalendar}.
     49  *
     50  * @author Laura Werner
     51  * @author Alan Liu
     52  * @internal
     53  */
     54 class U_I18N_API CalendarAstronomer : public UMemory {
     55 public:
     56   // some classes
     57 
     58 public:
     59   /**
     60    * Represents the position of an object in the sky relative to the ecliptic,
     61    * the plane of the earth's orbit around the Sun.
     62    * This is a spherical coordinate system in which the latitude
     63    * specifies the position north or south of the plane of the ecliptic.
     64    * The longitude specifies the position along the ecliptic plane
     65    * relative to the "First Point of Aries", which is the Sun's position in the sky
     66    * at the Vernal Equinox.
     67    * <p>
     68    * Note that Ecliptic objects are immutable and cannot be modified
     69    * once they are constructed.  This allows them to be passed and returned by
     70    * value without worrying about whether other code will modify them.
     71    *
     72    * @see CalendarAstronomer.Equatorial
     73    * @see CalendarAstronomer.Horizon
     74    * @internal
     75    */
     76   class U_I18N_API Ecliptic : public UMemory {
     77   public:
     78     /**
     79      * Constructs an Ecliptic coordinate object.
     80      * <p>
     81      * @param lat The ecliptic latitude, measured in radians.
     82      * @param lon The ecliptic longitude, measured in radians.
     83      * @internal
     84      */
     85     Ecliptic(double lat = 0, double lon = 0) {
     86       latitude = lat;
     87       longitude = lon;
     88     }
     89 
     90     /**
     91      * Setter for Ecliptic Coordinate object
     92      * @param lat The ecliptic latitude, measured in radians.
     93      * @param lon The ecliptic longitude, measured in radians.
     94      * @internal
     95      */
     96     void set(double lat, double lon) {
     97       latitude = lat;
     98       longitude = lon;
     99     }
    100 
    101     /**
    102      * Return a string representation of this object
    103      * @internal
    104      */
    105     UnicodeString toString() const;
    106 
    107     /**
    108      * The ecliptic latitude, in radians.  This specifies an object's
    109      * position north or south of the plane of the ecliptic,
    110      * with positive angles representing north.
    111      * @internal
    112      */
    113     double latitude;
    114 
    115     /**
    116      * The ecliptic longitude, in radians.
    117      * This specifies an object's position along the ecliptic plane
    118      * relative to the "First Point of Aries", which is the Sun's position
    119      * in the sky at the Vernal Equinox,
    120      * with positive angles representing east.
    121      * <p>
    122      * A bit of trivia: the first point of Aries is currently in the
    123      * constellation Pisces, due to the precession of the earth's axis.
    124      * @internal
    125      */
    126     double longitude;
    127   };
    128 
    129   /**
    130    * Represents the position of an
    131    * object in the sky relative to the plane of the earth's equator.
    132    * The <i>Right Ascension</i> specifies the position east or west
    133    * along the equator, relative to the sun's position at the vernal
    134    * equinox.  The <i>Declination</i> is the position north or south
    135    * of the equatorial plane.
    136    * <p>
    137    * Note that Equatorial objects are immutable and cannot be modified
    138    * once they are constructed.  This allows them to be passed and returned by
    139    * value without worrying about whether other code will modify them.
    140    *
    141    * @see CalendarAstronomer.Ecliptic
    142    * @see CalendarAstronomer.Horizon
    143    * @internal
    144    */
    145   class U_I18N_API Equatorial : public UMemory {
    146   public:
    147     /**
    148      * Constructs an Equatorial coordinate object.
    149      * <p>
    150      * @param asc The right ascension, measured in radians.
    151      * @param dec The declination, measured in radians.
    152      * @internal
    153      */
    154     Equatorial(double asc = 0, double dec = 0)
    155       : ascension(asc), declination(dec) { }
    156 
    157     /**
    158      * Setter
    159      * @param asc The right ascension, measured in radians.
    160      * @param dec The declination, measured in radians.
    161      * @internal
    162      */
    163     void set(double asc, double dec) {
    164       ascension = asc;
    165       declination = dec;
    166     }
    167 
    168     /**
    169      * Return a string representation of this object, with the
    170      * angles measured in degrees.
    171      * @internal
    172      */
    173     UnicodeString toString() const;
    174 
    175     /**
    176      * Return a string representation of this object with the right ascension
    177      * measured in hours, minutes, and seconds.
    178      * @internal
    179      */
    180     //String toHmsString() {
    181     //return radToHms(ascension) + "," + radToDms(declination);
    182     //}
    183 
    184     /**
    185      * The right ascension, in radians.
    186      * This is the position east or west along the equator
    187      * relative to the sun's position at the vernal equinox,
    188      * with positive angles representing East.
    189      * @internal
    190      */
    191     double ascension;
    192 
    193     /**
    194      * The declination, in radians.
    195      * This is the position north or south of the equatorial plane,
    196      * with positive angles representing north.
    197      * @internal
    198      */
    199     double declination;
    200   };
    201 
    202   /**
    203    * Represents the position of an  object in the sky relative to
    204    * the local horizon.
    205    * The <i>Altitude</i> represents the object's elevation above the horizon,
    206    * with objects below the horizon having a negative altitude.
    207    * The <i>Azimuth</i> is the geographic direction of the object from the
    208    * observer's position, with 0 representing north.  The azimuth increases
    209    * clockwise from north.
    210    * <p>
    211    * Note that Horizon objects are immutable and cannot be modified
    212    * once they are constructed.  This allows them to be passed and returned by
    213    * value without worrying about whether other code will modify them.
    214    *
    215    * @see CalendarAstronomer.Ecliptic
    216    * @see CalendarAstronomer.Equatorial
    217    * @internal
    218    */
    219   class U_I18N_API Horizon : public UMemory {
    220   public:
    221     /**
    222      * Constructs a Horizon coordinate object.
    223      * <p>
    224      * @param alt  The altitude, measured in radians above the horizon.
    225      * @param azim The azimuth, measured in radians clockwise from north.
    226      * @internal
    227      */
    228     Horizon(double alt=0, double azim=0)
    229       : altitude(alt), azimuth(azim) { }
    230 
    231     /**
    232      * Setter for Ecliptic Coordinate object
    233      * @param alt  The altitude, measured in radians above the horizon.
    234      * @param azim The azimuth, measured in radians clockwise from north.
    235      * @internal
    236      */
    237     void set(double alt, double azim) {
    238       altitude = alt;
    239       azimuth = azim;
    240     }
    241 
    242     /**
    243      * Return a string representation of this object, with the
    244      * angles measured in degrees.
    245      * @internal
    246      */
    247     UnicodeString toString() const;
    248 
    249     /**
    250      * The object's altitude above the horizon, in radians.
    251      * @internal
    252      */
    253     double altitude;
    254 
    255     /**
    256      * The object's direction, in radians clockwise from north.
    257      * @internal
    258      */
    259     double azimuth;
    260   };
    261 
    262 public:
    263   //-------------------------------------------------------------------------
    264   // Assorted private data used for conversions
    265   //-------------------------------------------------------------------------
    266 
    267   // My own copies of these so compilers are more likely to optimize them away
    268   static const double PI;
    269 
    270   /**
    271    * The average number of solar days from one new moon to the next.  This is the time
    272    * it takes for the moon to return the same ecliptic longitude as the sun.
    273    * It is longer than the sidereal month because the sun's longitude increases
    274    * during the year due to the revolution of the earth around the sun.
    275    * Approximately 29.53.
    276    *
    277    * @see #SIDEREAL_MONTH
    278    * @internal
    279    * @deprecated ICU 2.4. This class may be removed or modified.
    280    */
    281   static const double SYNODIC_MONTH;
    282 
    283   //-------------------------------------------------------------------------
    284   // Constructors
    285   //-------------------------------------------------------------------------
    286 
    287   /**
    288    * Construct a new <code>CalendarAstronomer</code> object that is initialized to
    289    * the current date and time.
    290    * @internal
    291    */
    292   CalendarAstronomer();
    293 
    294   /**
    295    * Construct a new <code>CalendarAstronomer</code> object that is initialized to
    296    * the specified date and time.
    297    * @internal
    298    */
    299   CalendarAstronomer(UDate d);
    300 
    301   /**
    302    * Construct a new <code>CalendarAstronomer</code> object with the given
    303    * latitude and longitude.  The object's time is set to the current
    304    * date and time.
    305    * <p>
    306    * @param longitude The desired longitude, in <em>degrees</em> east of
    307    *                  the Greenwich meridian.
    308    *
    309    * @param latitude  The desired latitude, in <em>degrees</em>.  Positive
    310    *                  values signify North, negative South.
    311    *
    312    * @see java.util.Date#getTime()
    313    * @internal
    314    */
    315   CalendarAstronomer(double longitude, double latitude);
    316 
    317   /**
    318    * Destructor
    319    * @internal
    320    */
    321   ~CalendarAstronomer();
    322 
    323   //-------------------------------------------------------------------------
    324   // Time and date getters and setters
    325   //-------------------------------------------------------------------------
    326 
    327   /**
    328    * Set the current date and time of this <code>CalendarAstronomer</code> object.  All
    329    * astronomical calculations are performed based on this time setting.
    330    *
    331    * @param aTime the date and time, expressed as the number of milliseconds since
    332    *              1/1/1970 0:00 GMT (Gregorian).
    333    *
    334    * @see #setDate
    335    * @see #getTime
    336    * @internal
    337    */
    338   void setTime(UDate aTime);
    339 
    340 
    341   /**
    342    * Set the current date and time of this <code>CalendarAstronomer</code> object.  All
    343    * astronomical calculations are performed based on this time setting.
    344    *
    345    * @param aTime the date and time, expressed as the number of milliseconds since
    346    *              1/1/1970 0:00 GMT (Gregorian).
    347    *
    348    * @see #getTime
    349    * @internal
    350    */
    351   void setDate(UDate aDate) { setTime(aDate); }
    352 
    353   /**
    354    * Set the current date and time of this <code>CalendarAstronomer</code> object.  All
    355    * astronomical calculations are performed based on this time setting.
    356    *
    357    * @param jdn   the desired time, expressed as a "julian day number",
    358    *              which is the number of elapsed days since
    359    *              1/1/4713 BC (Julian), 12:00 GMT.  Note that julian day
    360    *              numbers start at <em>noon</em>.  To get the jdn for
    361    *              the corresponding midnight, subtract 0.5.
    362    *
    363    * @see #getJulianDay
    364    * @see #JULIAN_EPOCH_MS
    365    * @internal
    366    */
    367   void setJulianDay(double jdn);
    368 
    369   /**
    370    * Get the current time of this <code>CalendarAstronomer</code> object,
    371    * represented as the number of milliseconds since
    372    * 1/1/1970 AD 0:00 GMT (Gregorian).
    373    *
    374    * @see #setTime
    375    * @see #getDate
    376    * @internal
    377    */
    378   UDate getTime();
    379 
    380   /**
    381    * Get the current time of this <code>CalendarAstronomer</code> object,
    382    * expressed as a "julian day number", which is the number of elapsed
    383    * days since 1/1/4713 BC (Julian), 12:00 GMT.
    384    *
    385    * @see #setJulianDay
    386    * @see #JULIAN_EPOCH_MS
    387    * @internal
    388    */
    389   double getJulianDay();
    390 
    391   /**
    392    * Return this object's time expressed in julian centuries:
    393    * the number of centuries after 1/1/1900 AD, 12:00 GMT
    394    *
    395    * @see #getJulianDay
    396    * @internal
    397    */
    398   double getJulianCentury();
    399 
    400   /**
    401    * Returns the current Greenwich sidereal time, measured in hours
    402    * @internal
    403    */
    404   double getGreenwichSidereal();
    405 
    406 private:
    407   double getSiderealOffset();
    408 public:
    409   /**
    410    * Returns the current local sidereal time, measured in hours
    411    * @internal
    412    */
    413   double getLocalSidereal();
    414 
    415   /**
    416    * Converts local sidereal time to Universal Time.
    417    *
    418    * @param lst   The Local Sidereal Time, in hours since sidereal midnight
    419    *              on this object's current date.
    420    *
    421    * @return      The corresponding Universal Time, in milliseconds since
    422    *              1 Jan 1970, GMT.
    423    */
    424   //private:
    425   double lstToUT(double lst);
    426 
    427   /**
    428    *
    429    * Convert from ecliptic to equatorial coordinates.
    430    *
    431    * @param ecliptic     The ecliptic
    432    * @param result       Fillin result
    433    * @return reference to result
    434    */
    435   Equatorial& eclipticToEquatorial(Equatorial& result, const Ecliptic& ecliptic);
    436 
    437   /**
    438    * Convert from ecliptic to equatorial coordinates.
    439    *
    440    * @param eclipLong     The ecliptic longitude
    441    * @param eclipLat      The ecliptic latitude
    442    *
    443    * @return              The corresponding point in equatorial coordinates.
    444    * @internal
    445    */
    446   Equatorial& eclipticToEquatorial(Equatorial& result, double eclipLong, double eclipLat);
    447 
    448   /**
    449    * Convert from ecliptic longitude to equatorial coordinates.
    450    *
    451    * @param eclipLong     The ecliptic longitude
    452    *
    453    * @return              The corresponding point in equatorial coordinates.
    454    * @internal
    455    */
    456   Equatorial& eclipticToEquatorial(Equatorial& result, double eclipLong) ;
    457 
    458   /**
    459    * @internal
    460    */
    461   Horizon& eclipticToHorizon(Horizon& result, double eclipLong) ;
    462 
    463   //-------------------------------------------------------------------------
    464   // The Sun
    465   //-------------------------------------------------------------------------
    466 
    467   /**
    468    * The longitude of the sun at the time specified by this object.
    469    * The longitude is measured in radians along the ecliptic
    470    * from the "first point of Aries," the point at which the ecliptic
    471    * crosses the earth's equatorial plane at the vernal equinox.
    472    * <p>
    473    * Currently, this method uses an approximation of the two-body Kepler's
    474    * equation for the earth and the sun.  It does not take into account the
    475    * perturbations caused by the other planets, the moon, etc.
    476    * @internal
    477    */
    478   double getSunLongitude();
    479 
    480   /**
    481    * TODO Make this public when the entire class is package-private.
    482    */
    483   /*public*/ void getSunLongitude(double julianDay, double &longitude, double &meanAnomaly);
    484 
    485   /**
    486    * The position of the sun at this object's current date and time,
    487    * in equatorial coordinates.
    488    * @param result fillin for the result
    489    * @internal
    490    */
    491   Equatorial& getSunPosition(Equatorial& result);
    492 
    493 public:
    494   /**
    495    * Constant representing the vernal equinox.
    496    * For use with {@link #getSunTime getSunTime}.
    497    * Note: In this case, "vernal" refers to the northern hemisphere's seasons.
    498    * @internal
    499    */
    500 //  static double VERNAL_EQUINOX();
    501 
    502   /**
    503    * Constant representing the summer solstice.
    504    * For use with {@link #getSunTime getSunTime}.
    505    * Note: In this case, "summer" refers to the northern hemisphere's seasons.
    506    * @internal
    507    */
    508   static double SUMMER_SOLSTICE();
    509 
    510   /**
    511    * Constant representing the autumnal equinox.
    512    * For use with {@link #getSunTime getSunTime}.
    513    * Note: In this case, "autumn" refers to the northern hemisphere's seasons.
    514    * @internal
    515    */
    516 //  static double AUTUMN_EQUINOX();
    517 
    518   /**
    519    * Constant representing the winter solstice.
    520    * For use with {@link #getSunTime getSunTime}.
    521    * Note: In this case, "winter" refers to the northern hemisphere's seasons.
    522    * @internal
    523    */
    524   static double WINTER_SOLSTICE();
    525 
    526   /**
    527    * Find the next time at which the sun's ecliptic longitude will have
    528    * the desired value.
    529    * @internal
    530    */
    531   UDate getSunTime(double desired, UBool next);
    532 
    533   /**
    534    * Returns the time (GMT) of sunrise or sunset on the local date to which
    535    * this calendar is currently set.
    536    *
    537    * NOTE: This method only works well if this object is set to a
    538    * time near local noon.  Because of variations between the local
    539    * official time zone and the geographic longitude, the
    540    * computation can flop over into an adjacent day if this object
    541    * is set to a time near local midnight.
    542    *
    543    * @internal
    544    */
    545   UDate getSunRiseSet(UBool rise);
    546 
    547   //-------------------------------------------------------------------------
    548   // The Moon
    549   //-------------------------------------------------------------------------
    550 
    551   /**
    552    * The position of the moon at the time set on this
    553    * object, in equatorial coordinates.
    554    * @internal
    555    * @return const reference to internal field of calendar astronomer. Do not use outside of the lifetime of this astronomer.
    556    */
    557   const Equatorial& getMoonPosition();
    558 
    559   /**
    560    * The "age" of the moon at the time specified in this object.
    561    * This is really the angle between the
    562    * current ecliptic longitudes of the sun and the moon,
    563    * measured in radians.
    564    *
    565    * @see #getMoonPhase
    566    * @internal
    567    */
    568   double getMoonAge();
    569 
    570   /**
    571    * Calculate the phase of the moon at the time set in this object.
    572    * The returned phase is a <code>double</code> in the range
    573    * <code>0 <= phase < 1</code>, interpreted as follows:
    574    * <ul>
    575    * <li>0.00: New moon
    576    * <li>0.25: First quarter
    577    * <li>0.50: Full moon
    578    * <li>0.75: Last quarter
    579    * </ul>
    580    *
    581    * @see #getMoonAge
    582    * @internal
    583    */
    584   double getMoonPhase();
    585 
    586   class U_I18N_API MoonAge : public UMemory {
    587   public:
    588     MoonAge(double l)
    589       :  value(l) { }
    590     void set(double l) { value = l; }
    591     double value;
    592   };
    593 
    594   /**
    595    * Constant representing a new moon.
    596    * For use with {@link #getMoonTime getMoonTime}
    597    * @internal
    598    */
    599   static const MoonAge NEW_MOON();
    600 
    601   /**
    602    * Constant representing the moon's first quarter.
    603    * For use with {@link #getMoonTime getMoonTime}
    604    * @internal
    605    */
    606 //  static const MoonAge FIRST_QUARTER();
    607 
    608   /**
    609    * Constant representing a full moon.
    610    * For use with {@link #getMoonTime getMoonTime}
    611    * @internal
    612    */
    613   static const MoonAge FULL_MOON();
    614 
    615   /**
    616    * Constant representing the moon's last quarter.
    617    * For use with {@link #getMoonTime getMoonTime}
    618    * @internal
    619    */
    620 //  static const MoonAge LAST_QUARTER();
    621 
    622   /**
    623    * Find the next or previous time at which the Moon's ecliptic
    624    * longitude will have the desired value.
    625    * <p>
    626    * @param desired   The desired longitude.
    627    * @param next      <tt>true</tt> if the next occurrance of the phase
    628    *                  is desired, <tt>false</tt> for the previous occurrance.
    629    * @internal
    630    */
    631   UDate getMoonTime(double desired, UBool next);
    632   UDate getMoonTime(const MoonAge& desired, UBool next);
    633 
    634   /**
    635    * Returns the time (GMT) of sunrise or sunset on the local date to which
    636    * this calendar is currently set.
    637    * @internal
    638    */
    639   UDate getMoonRiseSet(UBool rise);
    640 
    641   //-------------------------------------------------------------------------
    642   // Interpolation methods for finding the time at which a given event occurs
    643   //-------------------------------------------------------------------------
    644 
    645   // private
    646   class AngleFunc : public UMemory {
    647   public:
    648     virtual double eval(CalendarAstronomer&) = 0;
    649     virtual ~AngleFunc();
    650   };
    651   friend class AngleFunc;
    652 
    653   UDate timeOfAngle(AngleFunc& func, double desired,
    654                     double periodDays, double epsilon, UBool next);
    655 
    656   class CoordFunc : public UMemory {
    657   public:
    658     virtual void eval(Equatorial& result, CalendarAstronomer&) = 0;
    659     virtual ~CoordFunc();
    660   };
    661   friend class CoordFunc;
    662 
    663   double riseOrSet(CoordFunc& func, UBool rise,
    664                    double diameter, double refraction,
    665                    double epsilon);
    666 
    667   //-------------------------------------------------------------------------
    668   // Other utility methods
    669   //-------------------------------------------------------------------------
    670 private:
    671 
    672   /**
    673    * Return the obliquity of the ecliptic (the angle between the ecliptic
    674    * and the earth's equator) at the current time.  This varies due to
    675    * the precession of the earth's axis.
    676    *
    677    * @return  the obliquity of the ecliptic relative to the equator,
    678    *          measured in radians.
    679    */
    680   double eclipticObliquity();
    681 
    682   //-------------------------------------------------------------------------
    683   // Private data
    684   //-------------------------------------------------------------------------
    685 private:
    686   /**
    687    * Current time in milliseconds since 1/1/1970 AD
    688    * @see java.util.Date#getTime
    689    */
    690   UDate fTime;
    691 
    692   /* These aren't used yet, but they'll be needed for sunset calculations
    693    * and equatorial to horizon coordinate conversions
    694    */
    695   double fLongitude;
    696   double fLatitude;
    697   double fGmtOffset;
    698 
    699   //
    700   // The following fields are used to cache calculated results for improved
    701   // performance.  These values all depend on the current time setting
    702   // of this object, so the clearCache method is provided.
    703   //
    704 
    705   double    julianDay;
    706   double    julianCentury;
    707   double    sunLongitude;
    708   double    meanAnomalySun;
    709   double    moonLongitude;
    710   double    moonEclipLong;
    711   double    meanAnomalyMoon;
    712   double    eclipObliquity;
    713   double    siderealT0;
    714   double    siderealTime;
    715 
    716   void clearCache();
    717 
    718   Equatorial  moonPosition;
    719   UBool       moonPositionSet;
    720 
    721   /**
    722    * @internal
    723    */
    724 //  UDate local(UDate localMillis);
    725 };
    726 
    727 U_NAMESPACE_END
    728 
    729 struct UHashtable;
    730 
    731 U_NAMESPACE_BEGIN
    732 
    733 /**
    734  * Cache of month -> julian day
    735  * @internal
    736  */
    737 class CalendarCache : public UMemory {
    738 public:
    739   static int32_t get(CalendarCache** cache, int32_t key, UErrorCode &status);
    740   static void put(CalendarCache** cache, int32_t key, int32_t value, UErrorCode &status);
    741   virtual ~CalendarCache();
    742 private:
    743   CalendarCache(int32_t size, UErrorCode& status);
    744   static void createCache(CalendarCache** cache, UErrorCode& status);
    745   /**
    746    * not implemented
    747    */
    748   CalendarCache();
    749   UHashtable *fTable;
    750 };
    751 
    752 U_NAMESPACE_END
    753 
    754 #endif
    755 #endif
    756