Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-06-11 03:00:13

0001 #ifndef L1Trigger_TrackFindingTracklet_DataFormats_h
0002 #define L1Trigger_TrackFindingTracklet_DataFormats_h
0003 
0004 /*----------------------------------------------------------------------
0005 Classes to calculate and provide dataformats used by Hybrid emulator
0006 enabling automated conversions from frames to stubs/tracks and vice versa
0007 In data members of classes Stub* & Track* below, the variables describing
0008 stubs/tracks are stored both in digitial format as a 64b word in frame_,
0009 and in undigitized format in an std::tuple. (This saves CPU)
0010 ----------------------------------------------------------------------*/
0011 
0012 #include "FWCore/Framework/interface/data_default_record_trait.h"
0013 #include "L1Trigger/TrackFindingTracklet/interface/ChannelAssignment.h"
0014 #include "L1Trigger/TrackTrigger/interface/Setup.h"
0015 #include "DataFormats/L1TrackTrigger/interface/TTBV.h"
0016 
0017 #include <vector>
0018 #include <cmath>
0019 #include <initializer_list>
0020 #include <tuple>
0021 #include <iostream>
0022 #include <string>
0023 
0024 namespace trklet {
0025 
0026   // hybrid processes
0027   enum class Process { begin, tm = begin, dr, kf, tfp, end, x };
0028   // hybrid variables
0029   enum class Variable { begin, stubId = begin, r, phi, z, dPhi, dZ, inv2R, phiT, cot, zT, end, x };
0030   // hybrid process order
0031   constexpr std::initializer_list<Process> Processes = {Process::tm, Process::dr, Process::kf, Process::tfp};
0032   // conversion: Process to int
0033   inline constexpr int operator+(Process p) { return static_cast<int>(p); }
0034   // conversion: Variable to int
0035   inline constexpr int operator+(Variable v) { return static_cast<int>(v); }
0036   // increment of Process
0037   inline constexpr Process operator++(Process p) { return Process(+p + 1); }
0038   // increment of Variable
0039   inline constexpr Variable operator++(Variable v) { return Variable(+v + 1); }
0040 
0041   //Base class representing format of a variable
0042   class DataFormat {
0043   public:
0044     DataFormat(bool twos, bool biased = true) : twos_(twos), width_(0), base_(1.), range_(0.) {}
0045     DataFormat(bool twos, int width, double base, double range)
0046         : twos_(twos), width_(width), base_(base), range_(range) {}
0047     DataFormat() {}
0048     ~DataFormat() = default;
0049     // converts int to bitvector
0050     TTBV ttBV(int i) const { return TTBV(i, width_, twos_); }
0051     // converts double to bitvector
0052     TTBV ttBV(double d) const { return TTBV(d, base_, width_, twos_); }
0053     // extracts int from bitvector, removing these bits from bitvector
0054     void extract(TTBV& in, int& out) const { out = in.extract(width_, twos_); }
0055     // extracts double from bitvector, removing these bits from bitvector
0056     void extract(TTBV& in, double& out) const { out = in.extract(base_, width_, twos_); }
0057     // extracts double from bitvector, removing these bits from bitvector
0058     void extract(TTBV& in, TTBV& out) const { out = in.slice(width_, twos_); }
0059     // extracts bool from bitvector, removing these bits from bitvector
0060     void extract(TTBV& in, bool& out) const { out = in.extract(); }
0061     // attaches integer to bitvector
0062     void attach(const int i, TTBV& ttBV) const { ttBV += TTBV(i, width_, twos_); }
0063     // attaches double to bitvector
0064     void attach(const double d, TTBV& ttBV) const { ttBV += TTBV(d, base_, width_, twos_); }
0065     // attaches bitvector to bitvector
0066     void attach(const TTBV& bv, TTBV& ttBV) const { ttBV += bv; }
0067     // converts int to double
0068     double floating(int i) const { return (i + .5) * base_; }
0069     // converts double to int
0070     int integer(double d) const { return std::floor(d / base_ + 1.e-12); }
0071     // converts double to int and back to double
0072     double digi(double d) const { return floating(integer(d)); }
0073     // converts binary integer value to twos complement integer value
0074     int toSigned(int i) const { return i - std::pow(2, width_) / 2; }
0075     // converts twos complement integer value to binary integer value
0076     int toUnsigned(int i) const { return i + std::pow(2, width_) / 2; }
0077     // converts floating point value to binary integer value
0078     int toUnsigned(double d) const { return this->integer(d) + std::pow(2, width_) / 2; }
0079     // biggest representable floating point value
0080     double limit() const { return (range_ - base_) / (twos_ ? 2. : 1.); }
0081     // returns false if data format would oferflow for this double value
0082     bool inRange(double d, bool digi = true) const {
0083       const double range = digi ? base_ * pow(2, width_) : range_;
0084       return d >= -range / 2. && d < range / 2.;
0085     }
0086     // returns false if data format would oferflow for this int value
0087     bool inRange(int i) const { return inRange(floating(i)); }
0088     // true if twos'complement or false if binary representation is chosen
0089     bool twos() const { return twos_; }
0090     // number of used bits
0091     int width() const { return width_; }
0092     // precision
0093     double base() const { return base_; }
0094     // covered range
0095     double range() const { return range_; }
0096 
0097   protected:
0098     // true if twos'complement or false if binary representation is chosen
0099     bool twos_;
0100     // number of used bits
0101     int width_;
0102     // precision
0103     double base_;
0104     // covered range
0105     double range_;
0106   };
0107 
0108   // function template for DataFormat generation
0109   template <Variable v, Process p>
0110   DataFormat makeDataFormat(const ChannelAssignment* ca);
0111 
0112   template <>
0113   DataFormat makeDataFormat<Variable::inv2R, Process::tfp>(const ChannelAssignment* ca);
0114   template <>
0115   DataFormat makeDataFormat<Variable::phiT, Process::tfp>(const ChannelAssignment* ca);
0116   template <>
0117   DataFormat makeDataFormat<Variable::cot, Process::tfp>(const ChannelAssignment* ca);
0118   template <>
0119   DataFormat makeDataFormat<Variable::zT, Process::tfp>(const ChannelAssignment* ca);
0120 
0121   template <>
0122   DataFormat makeDataFormat<Variable::inv2R, Process::tm>(const ChannelAssignment* ca);
0123   template <>
0124   DataFormat makeDataFormat<Variable::phiT, Process::tm>(const ChannelAssignment* ca);
0125   template <>
0126   DataFormat makeDataFormat<Variable::zT, Process::tm>(const ChannelAssignment* ca);
0127   template <>
0128   DataFormat makeDataFormat<Variable::cot, Process::tm>(const ChannelAssignment* ca);
0129 
0130   template <>
0131   DataFormat makeDataFormat<Variable::stubId, Process::tm>(const ChannelAssignment* ca);
0132   template <>
0133   DataFormat makeDataFormat<Variable::r, Process::tm>(const ChannelAssignment* ca);
0134   template <>
0135   DataFormat makeDataFormat<Variable::phi, Process::tm>(const ChannelAssignment* ca);
0136   template <>
0137   DataFormat makeDataFormat<Variable::z, Process::tm>(const ChannelAssignment* ca);
0138   template <>
0139   DataFormat makeDataFormat<Variable::dPhi, Process::tm>(const ChannelAssignment* ca);
0140   template <>
0141   DataFormat makeDataFormat<Variable::dZ, Process::tm>(const ChannelAssignment* ca);
0142 
0143   template <>
0144   DataFormat makeDataFormat<Variable::inv2R, Process::kf>(const ChannelAssignment* ca);
0145   template <>
0146   DataFormat makeDataFormat<Variable::phiT, Process::kf>(const ChannelAssignment* ca);
0147   template <>
0148   DataFormat makeDataFormat<Variable::cot, Process::kf>(const ChannelAssignment* ca);
0149   template <>
0150   DataFormat makeDataFormat<Variable::zT, Process::kf>(const ChannelAssignment* ca);
0151 
0152   /*! \class  trklet::DataFormats
0153    *  \brief  Class to calculate and provide dataformats used by Hybrid emulator
0154    *  \author Thomas Schuh
0155    *  \date   2024, Sep
0156    */
0157   class DataFormats {
0158   private:
0159     // variable flavour mapping, Each row below declares which processing steps use the variable named in the comment at the end of the row
0160     static constexpr std::array<std::array<Process, +Process::end>, +Variable::end> config_ = {{
0161         //  Process::tm  Process::dr   Process::kf   Process::tfp
0162         {{Process::tm, Process::x, Process::x, Process::x}},      // Variable::stubId
0163         {{Process::tm, Process::tm, Process::tm, Process::x}},    // Variable::r
0164         {{Process::tm, Process::tm, Process::tm, Process::x}},    // Variable::phi
0165         {{Process::tm, Process::tm, Process::tm, Process::x}},    // Variable::z
0166         {{Process::tm, Process::tm, Process::tm, Process::x}},    // Variable::dPhi
0167         {{Process::tm, Process::tm, Process::tm, Process::x}},    // Variable::dZ
0168         {{Process::tm, Process::tm, Process::kf, Process::tfp}},  // Variable::inv2R
0169         {{Process::tm, Process::tm, Process::kf, Process::tfp}},  // Variable::phiT
0170         {{Process::tm, Process::tm, Process::kf, Process::tfp}},  // Variable::cot
0171         {{Process::tm, Process::tm, Process::kf, Process::tfp}}   // Variable::zT
0172     }};
0173     // stub word assembly, shows which stub variables are used by each process
0174     static constexpr std::array<std::initializer_list<Variable>, +Process::end> stubs_ = {{
0175         {Variable::stubId, Variable::r, Variable::phi, Variable::z},              // Process::tm
0176         {Variable::r, Variable::phi, Variable::z, Variable::dPhi, Variable::dZ},  // Process::dr
0177         {Variable::r, Variable::phi, Variable::z, Variable::dPhi, Variable::dZ},  // Process::kf
0178         {}                                                                        // Process::tfp
0179     }};
0180     // track word assembly, shows which track variables are used by each process
0181     static constexpr std::array<std::initializer_list<Variable>, +Process::end> tracks_ = {{
0182         {Variable::inv2R, Variable::phiT, Variable::zT},                 // Process::tm
0183         {Variable::inv2R, Variable::phiT, Variable::zT},                 // Process::dr
0184         {Variable::inv2R, Variable::phiT, Variable::cot, Variable::zT},  // Process::kf
0185         {}                                                               // Process::tfp
0186     }};
0187 
0188   public:
0189     DataFormats();
0190     DataFormats(const ChannelAssignment* ca);
0191     ~DataFormats() = default;
0192     // converts bits to ntuple of variables
0193     template <typename... Ts>
0194     void convertStub(Process p, const tt::Frame& bv, std::tuple<Ts...>& data) const {
0195       TTBV ttBV(bv);
0196       extractStub(p, ttBV, data);
0197     }
0198     // converts ntuple of variables to bits
0199     template <typename... Ts>
0200     void convertStub(Process p, const std::tuple<Ts...>& data, tt::Frame& bv) const {
0201       TTBV ttBV(1, 1 + numUnusedBitsStubs_[+p]);
0202       attachStub(p, data, ttBV);
0203       bv = ttBV.bs();
0204     }
0205     // converts bits to ntuple of variables
0206     template <typename... Ts>
0207     void convertTrack(Process p, const tt::Frame& bv, std::tuple<Ts...>& data) const {
0208       TTBV ttBV(bv);
0209       extractTrack(p, ttBV, data);
0210     }
0211     // converts ntuple of variables to bits
0212     template <typename... Ts>
0213     void convertTrack(Process p, const std::tuple<Ts...>& data, tt::Frame& bv) const {
0214       TTBV ttBV(1, 1 + numUnusedBitsTracks_[+p]);
0215       attachTrack(p, data, ttBV);
0216       bv = ttBV.bs();
0217     }
0218     // access to run-time constants
0219     const tt::Setup* setup() const { return channelAssignment_->setup(); }
0220     // number of bits being used for specific variable flavour
0221     int width(Variable v, Process p) const { return formats_[+v][+p]->width(); }
0222     // precision being used for specific variable flavour
0223     double base(Variable v, Process p) const { return formats_[+v][+p]->base(); }
0224     // covered range for specific variable flavour
0225     double range(Variable v, Process p) const { return formats_[+v][+p]->range(); }
0226     // access to spedific format
0227     const DataFormat& format(Variable v, Process p) const { return *formats_[+v][+p]; }
0228 
0229   private:
0230     // number of unique data formats
0231     int numDataFormats_;
0232     // method to count number of unique data formats
0233     template <Variable v = Variable::begin, Process p = Process::begin>
0234     void countFormats();
0235     // constructs data formats of all unique used variables and flavours
0236     template <Variable v = Variable::begin, Process p = Process::begin>
0237     void fillDataFormats();
0238     // helper (loop) data formats of all unique used variables and flavours
0239     template <Variable v, Process p, Process it = Process::begin>
0240     void fillFormats();
0241     // helper (loop) to convert bits to ntuple of variables
0242     template <int it = 0, typename... Ts>
0243     void extractStub(Process p, TTBV& ttBV, std::tuple<Ts...>& data) const {
0244       Variable v = *std::next(stubs_[+p].begin(), sizeof...(Ts) - 1 - it);
0245       formats_[+v][+p]->extract(ttBV, std::get<sizeof...(Ts) - 1 - it>(data));
0246       if constexpr (it + 1 != sizeof...(Ts))
0247         extractStub<it + 1>(p, ttBV, data);
0248     }
0249     // helper (loop) to convert bits to ntuple of variables
0250     template <int it = 0, typename... Ts>
0251     void extractTrack(Process p, TTBV& ttBV, std::tuple<Ts...>& data) const {
0252       Variable v = *std::next(tracks_[+p].begin(), sizeof...(Ts) - 1 - it);
0253       formats_[+v][+p]->extract(ttBV, std::get<sizeof...(Ts) - 1 - it>(data));
0254       if constexpr (it + 1 != sizeof...(Ts))
0255         extractTrack<it + 1>(p, ttBV, data);
0256     }
0257     // helper (loop) to convert ntuple of variables to bits
0258     template <int it = 0, typename... Ts>
0259     void attachStub(Process p, const std::tuple<Ts...>& data, TTBV& ttBV) const {
0260       Variable v = *std::next(stubs_[+p].begin(), it);
0261       formats_[+v][+p]->attach(std::get<it>(data), ttBV);
0262       if constexpr (it + 1 != sizeof...(Ts))
0263         attachStub<it + 1>(p, data, ttBV);
0264     }
0265     // helper (loop) to convert ntuple of variables to bits
0266     template <int it = 0, typename... Ts>
0267     void attachTrack(Process p, const std::tuple<Ts...>& data, TTBV& ttBV) const {
0268       Variable v = *std::next(tracks_[+p].begin(), it);
0269       formats_[+v][+p]->attach(std::get<it>(data), ttBV);
0270       if constexpr (it + 1 != sizeof...(Ts))
0271         attachTrack<it + 1>(p, data, ttBV);
0272     }
0273     // stored run-time constants
0274     const ChannelAssignment* channelAssignment_;
0275     // collection of unique formats
0276     std::vector<DataFormat> dataFormats_;
0277     // variable flavour mapping
0278     std::vector<std::vector<DataFormat*>> formats_;
0279     // number of unused frame bits for a all Stub flavours
0280     std::vector<int> numUnusedBitsStubs_;
0281     // number of unused frame bits for a all Track flavours
0282     std::vector<int> numUnusedBitsTracks_;
0283   };
0284 
0285   // base class to represent stubs
0286   template <typename... Ts>
0287   class Stub {
0288   public:
0289     // construct Stub from Frame
0290     Stub(const tt::FrameStub& fs, const DataFormats* df, Process p) : dataFormats_(df), p_(p), frame_(fs) {
0291       dataFormats_->convertStub(p_, frame_.second, data_);
0292     }
0293     template <typename... Others>
0294     // construct Stub from other Stub
0295     Stub(const Stub<Others...>& stub, Ts... data)
0296         : dataFormats_(stub.dataFormats()), p_(++stub.p()), frame_(stub.frame()), data_(data...) {
0297       dataFormats_->convertStub(p_, data_, frame_.second);
0298     }
0299     // construct Stub from TTStubRef
0300     Stub(const TTStubRef& ttStubRef, const DataFormats* df, Process p, Ts... data)
0301         : dataFormats_(df), p_(p), frame_(ttStubRef, tt::Frame()), data_(data...) {
0302       dataFormats_->convertStub(p_, data_, frame_.second);
0303     }
0304     Stub() {}
0305     virtual ~Stub() = default;
0306     // true if frame valid, false if gap in data stream
0307     explicit operator bool() const { return frame_.first.isNonnull(); }
0308     // access to DataFormats
0309     const DataFormats* dataFormats() const { return dataFormats_; }
0310     // stub flavour
0311     Process p() const { return p_; }
0312     // acess to frame
0313     const tt::FrameStub& frame() const { return frame_; }
0314 
0315   protected:
0316     // all dataformats
0317     const DataFormats* dataFormats_;
0318     // stub flavour
0319     Process p_;
0320     // underlying TTStubRef and bitvector
0321     tt::FrameStub frame_;
0322     // ntuple of variables this stub is assemled of
0323     std::tuple<Ts...> data_;
0324   };
0325 
0326   // class to represent stubs generated by process TrackMulitplexer
0327   class StubTM : public Stub<int, double, double, double> {
0328   public:
0329     // construct StubTM from Frame
0330     StubTM(const tt::FrameStub& fs, const DataFormats* df) : Stub(fs, df, Process::tm) {}
0331     // construct StubTM from TTStubRef
0332     StubTM(const TTStubRef& ttStubRef, const DataFormats* df, int stubId, double r, double phi, double z)
0333         : Stub(ttStubRef, df, Process::tm, stubId, r, phi, z) {}
0334     ~StubTM() override = default;
0335     // stub Id
0336     int stubId() const { return std::get<0>(data_); }
0337     // stub radius wrt chosenRofPhi
0338     double r() const { return std::get<1>(data_); }
0339     // stub phi wrt processing nonant centre
0340     double phi() const { return std::get<2>(data_); }
0341     // stub z
0342     double z() const { return std::get<3>(data_); }
0343   };
0344 
0345   // class to represent stubs generated by process DuplicateRemoval
0346   class StubDR : public Stub<double, double, double, double, double> {
0347   public:
0348     // construct StubDR from Frame
0349     StubDR(const tt::FrameStub& fs, const DataFormats* df) : Stub(fs, df, Process::dr) {}
0350     // construct StubDR from StubTM
0351     StubDR(const StubTM& stub, double r, double phi, double z, double dPhi, double dZ)
0352         : Stub(stub, r, phi, z, dPhi, dZ) {}
0353     ~StubDR() override = default;
0354     // stub radius wrt chosenRofPhi
0355     double r() const { return std::get<0>(data_); }
0356     // stub phi wrt phi sector centre
0357     double phi() const { return std::get<1>(data_); }
0358     // stub z residual wrt eta sector
0359     double z() const { return std::get<2>(data_); }
0360     // stub phi uncertainty
0361     double dPhi() const { return std::get<3>(data_); }
0362     // stub z uncertainty
0363     double dZ() const { return std::get<4>(data_); }
0364   };
0365 
0366   // class to represent stubs generated by process KalmanFilter
0367   class StubKF : public Stub<double, double, double, double, double> {
0368   public:
0369     // construct StubKF from Frame
0370     StubKF(const tt::FrameStub& fs, const DataFormats* df) : Stub(fs, df, Process::kf) {}
0371     // construct StubKF from StubDR
0372     StubKF(const StubDR& stub, double r, double phi, double z, double dPhi, double dZ)
0373         : Stub(stub, r, phi, z, dPhi, dZ) {}
0374     ~StubKF() override = default;
0375     // stub radius wrt chosenRofPhi
0376     double r() const { return std::get<0>(data_); };
0377     // stub phi residual wrt track parameter
0378     double phi() const { return std::get<1>(data_); };
0379     // stub z residual wrt eta sector
0380     double z() const { return std::get<2>(data_); };
0381     // stub phi uncertainty
0382     double dPhi() const { return std::get<3>(data_); }
0383     // stub z uncertainty
0384     double dZ() const { return std::get<4>(data_); }
0385   };
0386 
0387   // base class to represent tracks
0388   template <typename... Ts>
0389   class Track {
0390   public:
0391     // construct Track from Frame
0392     Track(const tt::FrameTrack& ft, const DataFormats* df, Process p) : dataFormats_(df), p_(p), frame_(ft) {
0393       dataFormats_->convertTrack(p_, frame_.second, data_);
0394     }
0395     // construct Track from TTTrackRef
0396     Track(const TTTrackRef& ttTrackRef, const DataFormats* df, Process p, Ts... data)
0397         : dataFormats_(df), p_(p), frame_(ttTrackRef, tt::Frame()), data_(data...) {
0398       dataFormats_->convertTrack(p_, data_, frame_.second);
0399     }
0400     // construct Track from other Track
0401     template <typename... Others>
0402     Track(const Track<Others...>& track, Ts... data)
0403         : dataFormats_(track.dataFormats()), p_(++track.p()), frame_(track.frame()), data_(data...) {
0404       dataFormats_->convertTrack(p_, data_, frame_.second);
0405     }
0406     Track() {}
0407     virtual ~Track() = default;
0408     // true if frame valid, false if gap in data stream
0409     explicit operator bool() const { return frame_.first.isNonnull(); }
0410     // access to DataFormats
0411     const DataFormats* dataFormats() const { return dataFormats_; }
0412     // track flavour
0413     Process p() const { return p_; }
0414     // acces to frame
0415     const tt::FrameTrack& frame() const { return frame_; }
0416 
0417   protected:
0418     // all data formats
0419     const DataFormats* dataFormats_;
0420     // track flavour
0421     Process p_;
0422     // underlying TTTrackRef and bitvector
0423     tt::FrameTrack frame_;
0424     // ntuple of variables this track is assemled of
0425     std::tuple<Ts...> data_;
0426   };
0427 
0428   // class to represent tracks generated by process TrackMultiplexer
0429   class TrackTM : public Track<double, double, double> {
0430   public:
0431     // construct TrackTM from Frame
0432     TrackTM(const tt::FrameTrack& ft, const DataFormats* df) : Track(ft, df, Process::tm) {}
0433     // construct TrackTM from TTTrack
0434     TrackTM(const TTTrackRef& tTTrackRef, const DataFormats* df, double inv2R, double phiT, double zT)
0435         : Track(tTTrackRef, df, Process::tm, inv2R, phiT, zT) {}
0436     ~TrackTM() override = default;
0437     // track inv2R
0438     double inv2R() const { return std::get<0>(data_); }
0439     // track phi at radius chosenRofPhi wrt pprocessing centre
0440     double phiT() const { return std::get<1>(data_); }
0441     // track z at radius chosenRofZ
0442     double zT() const { return std::get<2>(data_); }
0443   };
0444 
0445   // class to represent tracks generated by process DuplicateRemoval
0446   class TrackDR : public Track<double, double, double> {
0447   public:
0448     // construct TrackDR from Frame
0449     TrackDR(const tt::FrameTrack& ft, const DataFormats* df) : Track(ft, df, Process::dr) {}
0450     // construct TrackDR from TrackTM
0451     TrackDR(const TrackTM& track) : Track(track, track.inv2R(), track.phiT(), track.zT()) {}
0452     ~TrackDR() override = default;
0453     // track qOver pt
0454     double inv2R() const { return std::get<0>(data_); }
0455     // track phi at radius chosenRofPhi wrt processing nonant centre
0456     double phiT() const { return std::get<1>(data_); }
0457     // track z at radius chosenRofZ
0458     double zT() const { return std::get<2>(data_); }
0459   };
0460 
0461   // class to represent tracks generated by process KalmanFilter
0462   class TrackKF : public Track<double, double, double, double> {
0463   public:
0464     // construct TrackKF from Frame
0465     TrackKF(const tt::FrameTrack& ft, const DataFormats* df) : Track(ft, df, Process::kf) {}
0466     // construct TrackKF from TrackDR
0467     TrackKF(const TrackDR& track, double inv2R, double phiT, double cot, double zT)
0468         : Track(track, inv2R, phiT, cot, zT) {}
0469     TrackKF() {}
0470     ~TrackKF() override = default;
0471     // track inv2R
0472     double inv2R() const { return std::get<0>(data_); }
0473     // track phi at radius 0 wrt processing nonant centre
0474     double phiT() const { return std::get<1>(data_); }
0475     // track cotThea
0476     double cot() const { return std::get<2>(data_); }
0477     // track z at radius 0
0478     double zT() const { return std::get<3>(data_); }
0479   };
0480 
0481 }  // namespace trklet
0482 
0483 EVENTSETUP_DATA_DEFAULT_RECORD(trklet::DataFormats, trklet::ChannelAssignmentRcd);
0484 
0485 #endif