1 /* ***** BEGIN LICENSE BLOCK *****
2 *
3 * $Id: wavelet_utils.h,v 1.32 2008/10/20 04:21:02 asuraparaju Exp $ $Name: Dirac_1_0_2 $
4 *
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 *
7 * The contents of this file are subject to the Mozilla Public License
8 * Version 1.1 (the "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
11 *
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
14 * the specific language governing rights and limitations under the License.
15 *
16 * The Original Code is BBC Research and Development code.
17 *
18 * The Initial Developer of the Original Code is the British Broadcasting
19 * Corporation.
20 * Portions created by the Initial Developer are Copyright (C) 2004.
21 * All Rights Reserved.
22 *
23 * Contributor(s): Thomas Davies (Original Author),
24 *                 Scott R Ladd
25 *                 Anuradha Suraparaju
26 *
27 * Alternatively, the contents of this file may be used under the terms of
28 * the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser
29 * Public License Version 2.1 (the "LGPL"), in which case the provisions of
30 * the GPL or the LGPL are applicable instead of those above. If you wish to
31 * allow use of your version of this file only under the terms of the either
32 * the GPL or LGPL and not to allow others to use your version of this file
33 * under the MPL, indicate your decision by deleting the provisions above
34 * and replace them with the notice and other provisions required by the GPL
35 * or LGPL. If you do not delete the provisions above, a recipient may use
36 * your version of this file under the terms of any one of the MPL, the GPL
37 * or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
39 
40 #ifndef _WAVELET_UTILS_H_
41 #define _WAVELET_UTILS_H_
42 
43 #include <libdirac_common/arrays.h>
44 #include <libdirac_common/common.h>
45 #include <vector>
46 #include <cmath>
47 #include <iostream>
48 
49 //utilities for subband and wavelet transforms
50 //Includes fast transform using lifting
51 
52 namespace dirac
53 {
54 
55     class PicArray;
56     class Subband;
57 
58     //! Class for encapsulating metadata concerning a block of coefficients in a subband
59     class CodeBlock
60     {
61 
62     friend class Subband;
63 
64     public:
65         //! Constructor
66         /*
67             Default constructor - sets all dimensions to zero
68         */
69         CodeBlock();
70 
71         //! Constructor
72         /*
73             Initialise the code block
74             \param    xstart  the x-coord of the first coefficient in the block
75             \param    xend    one past the last coefficient, horizontally
76             \param    ystart  the y-coord of the first coefficient in the block
77             \param    yend    one past the last coefficient, vertically
78         */
79         CodeBlock( const int xstart , const int ystart , const int xend , const int yend);
80 
81         //! Returns the horizontal start of the block
Xstart()82         int Xstart() const { return m_xstart; }
83 
84         //! Returns the vertical start of the block
Ystart()85         int Ystart() const { return m_ystart; }
86 
87         //! Returns one past the last coefficient coord, horizontally
Xend()88         int Xend() const { return m_xend; }
89 
90         //! Returns one past the last coefficient coord, vertically
Yend()91         int Yend() const { return m_yend; }
92 
93         //! Returns the width of the code block
Xl()94         int Xl() const { return m_xl; }
95 
96         //! Returns the height of the code block
Yl()97         int Yl() const { return m_yl; }
98 
99         //! Returns the quantisation index associated to the code block
QuantIndex()100         int QuantIndex() const{ return m_quantindex; }
101 
102         //! Returns true if the code-block is skipped, false if not
Skipped()103         bool Skipped() const { return m_skipped; }
104 
105         //! Sets the quantisation index
SetQuantIndex(const int quantindex)106         void SetQuantIndex( const int quantindex ){ m_quantindex = quantindex; }
107 
108         //! Sets whether the code block is skipped or not
SetSkip(bool skip)109         void SetSkip( bool skip ){ m_skipped = skip; }
110 
111     private:
112 
113         //! Initialise the code block
114         /*
115             Initialise the code block
116             \param    xstart  the x-coord of the first coefficient in the block
117             \param    xend    one past the last coefficient, horizontally
118             \param    ystart  the y-coord of the first coefficient in the block
119             \param    yend    one past the last coefficient, vertically
120         */
121         void Init( const int xstart , const int ystart , const int xend , const int yend );
122 
123     private:
124 
125         int m_xstart;
126         int m_ystart;
127         int m_xend;
128         int m_yend;
129         int m_xl;
130         int m_yl;
131 
132         int m_quantindex;
133 
134         bool m_skipped;
135     };
136 
137 
138     //! Class encapsulating all the metadata relating to a wavelet subband
139     class Subband
140     {
141     public:
142 
143         //! Default constructor
144         Subband();
145 
146         //! Constructor
147         /*!
148             The constructor parameters are
149             \param    xpos    the xposition of the subband when packed into a
150                               big array with all the others
151             \param    ypos    the xposition of the subband
152             \param    xlen    the width of the subband
153             \param    ylen    the height of the subband
154          */
155         Subband(int xpos, int ypos, int xlen, int ylen);
156 
157         //! Constructor
158         /*!
159             The constructor parameters are
160             \param    xpos    the xposition of the subband when packed into a
161                               big array with all the others
162             \param    ypos    the xposition of the subband
163             \param    xlen    the width of the subband
164             \param    ylen    the height of the subband
165             \param    d        the depth of the subband in the wavelet transform
166          */
167         Subband(int xpos, int ypos, int xlen, int ylen, int d);
168 
169         //! Destructor
170         ~Subband();
171 
172         //Default (shallow) copy constructor and operator= used
173 
174         //! Return the width of the subband
Xl()175         int Xl() const {return m_xl;}
176 
177         //! Return the horizontal position of the subband
Xp()178         int Xp() const {return m_xp;}
179 
180         //! Return the height of the subband
Yl()181         int Yl() const {return m_yl;}
182 
183         //! Return the vertical position of the subband
Yp()184         int Yp() const {return m_yp;}
185 
186         //! Return the index of the maximum bit of the largest coefficient
Max()187         int Max() const {return m_max_bit;}
188 
189         //! Return the subband perceptual weight
Wt()190         double Wt() const {return m_wt;}
191 
192         //! Return the depth of the subband in the transform
Depth()193         int Depth() const {return m_depth;}
194 
195         //! Return the scale of the subband, viewed as a subsampled version of the picture
Scale()196         int Scale() const {return ( 1<<m_depth );}
197 
198         //! Return a quantisation index
QuantIndex()199         int QuantIndex() const {return m_qindex;}
200 
201         //! Return a flag indicating whether we have separate quantisers for each code block
UsingMultiQuants()202         bool UsingMultiQuants() const {return m_multi_quants; }
203 
204         //! Return the index of the parent subband
Parent()205         int Parent() const {return m_parent;}
206 
207         //! Return the indices of any child subbands
Children()208         const std::vector<int>& Children() const {return m_children;}
209 
210         //! Return the index of a specific child band
Child(const int n)211         int Child(const int n) const {return m_children[n];}
212 
213         //! Return the code blocks
GetCodeBlocks()214         TwoDArray<CodeBlock>& GetCodeBlocks(){ return m_code_block_array; }
215 
216         //! Return the code blocks
GetCodeBlocks()217         const TwoDArray<CodeBlock>& GetCodeBlocks() const { return m_code_block_array; }
218 
219         //! Returns true if subband is skipped, false if not
Skipped()220         bool Skipped() const { return m_skipped; }
221 
222         //! Set the perceptual weight
223         void SetWt( const float w );
224 
225         //! Set the parent index
SetParent(const int p)226         void SetParent( const int p ){ m_parent=p; }
227 
228         //! Set the subband depth
SetDepth(const int d)229         void SetDepth( const int d ){ m_depth=d;}
230 
231         //! Set the index of the maximum bit of the largest coefficient
SetMax(const int m)232         void SetMax( const int m ){ m_max_bit=m; };
233 
234         //! Set the number of (spatial) quantisers in the subband. Creates code block structure
235         void SetNumBlocks( const int ynum , const int xnum );
236 
237         //! Set the quantisation index
SetQuantIndex(const int idx)238         void SetQuantIndex( const int idx){ m_qindex = idx; }
239 
240         //! Set the number of (spatial) quantisers in the subband. Creates code block structure
SetUsingMultiQuants(const bool multi)241         void SetUsingMultiQuants( const bool multi){ m_multi_quants = multi; }
242 
243         //! Set whether the subband is skipped or not
SetSkip(const bool skip)244         void SetSkip(const bool skip ){ m_skipped = skip; }
245 
246     private:
247         // subband bounds
248         int m_xp , m_yp , m_xl , m_yl;
249 
250         // perceptual weight for quantisation
251         double m_wt;
252 
253         // depth in the transform
254         int m_depth;
255 
256         // quantiser index
257         int m_qindex;
258 
259         // position of parent in a subband list
260         int m_parent;
261 
262         // positions of children in the subband list
263         std::vector<int> m_children;
264 
265         // position of the MSB of the largest absolute value
266         int m_max_bit;
267 
268         // The code blocks
269         TwoDArray<CodeBlock> m_code_block_array;
270 
271         // A flag indicating whether we're using one qf for each code block
272         bool m_multi_quants;
273 
274         // Whether the subband is skipped or not
275         bool m_skipped;
276     };
277 
278     //!    A class encapulating all the subbands produced by a transform
279     class SubbandList
280     {
281     public:
282         //! Constructor
SubbandList()283         SubbandList(){}
284 
285         //! Destructor
~SubbandList()286         ~SubbandList(){}
287 
288         //Default (shallow) copy constructor and operator= used
289         //! Initialise the list
290         void Init(const int depth,const int xlen,const int ylen);
291 
292         //! Return the length of the subband list
Length()293         int Length() const {return bands.size();}
294 
295         //! Return the subband at position n (1<=n<=length)
operator()296         Subband& operator()(const int n){return bands[n-1];}
297 
298         //! Return the subband at position n (1<=n<=length)
operator()299         const Subband& operator()(const int n) const {return bands[n-1];}
300 
301         //! Add a band to the list
AddBand(const Subband & b)302         void AddBand(const Subband& b){bands.push_back(b);}
303 
304         //! Remove all the bands from the list
Clear()305         void Clear(){bands.clear();}
306 
307     private:
308 
309         //! Given x and y spatial frequencies in cycles per degree, returns a weighting value
310         float PerceptualWeight( const float xf , const float yf , const CompSort cs);
311 
312     private:
313         std::vector<Subband> bands;
314     };
315 
316     class CoeffArray;
317         //! A virtual parent class to do vertical and horizontal splitting with wavelet filters
318         class VHFilter
319         {
320 
321         public:
322 
VHFilter()323             VHFilter(){}
324 
~VHFilter()325             virtual ~VHFilter(){}
326 
327             //! Split a subband into 4
328             virtual void Split(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data)=0;
329 
330             //! Create a single band from 4 quadrant bands
331             virtual void Synth(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data)=0;
332 
333             //! Return the value of the additional bitshift
334             virtual int GetShift() const =0;
335 
336         protected:
337 
338             //! Interleave data from separate subbands into even and odd positions for in-place calculation - called by Synth
339             inline void Interleave( const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data );
340 
341 
342             //! De-interleave data even and odd positions into separate subbands - called by Split
343             inline void DeInterleave( const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data );
344 
345             //! Shift all vals in Row by 'shift' bits to the left to increase accuracy by 'shift' bits. Used in Analysis stage of filter
346             void ShiftRowLeft(CoeffType *row, int length, int shift);
347 
348         //! Shift all vals in Row by 'shift' bits to the right to counter the shift in the Analysis stage. This function is used in the Synthesis stage
349             void ShiftRowRight(CoeffType *row, int length, int shift);
350         };
351 
352         //! Class to do Daubechies (9,7) filtering operations
353         class VHFilterDAUB9_7 : public VHFilter
354         {
355 
356         public:
357 
358             //! Split a subband into 4
359             void Split(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data);
360 
361             //! Create a single band from 4 quadrant bands
362             void Synth(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data);
363 
364             //! Return the value of the additional bitshift
GetShift()365             int GetShift() const {return 1;}
366 
367 
368         };
369 
370         //! Class to do (5,3) wavelet filtering operations
371         class VHFilterLEGALL5_3 : public VHFilter
372         {
373 
374         public:
375 
376             //! Split a subband into 4
377             void Split(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data);
378 
379             //! Create a single band from 4 quadrant bands
380             void Synth(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data);
381 
382            //! Return the value of the additional bitshift
GetShift()383             int GetShift() const {return 1;}
384 
385 
386 #ifdef HAVE_MMX
387             inline void HorizSynth (int xp, int xl, int ystart, int yend, CoeffArray &coeff_data);
388 #endif
389 
390         };
391 
392         //! A short filter that's actually close to Daubechies (9,7) but with just two lifting steps
393         class VHFilterDD9_7 : public VHFilter
394         {
395 
396         public:
397 
398             //! Split a subband into 4
399             void Split(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data);
400 
401             //! Create a single band from 4 quadrant bands
402             void Synth(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data);
403 
404             //! Return the value of the additional bitshift
GetShift()405             int GetShift() const {return 1;}
406         };
407 
408 
409         //! An extension of DD9_7, with a better low-pass filter but more computation
410         class VHFilterDD13_7 : public VHFilter
411         {
412 
413         public:
414 
415             //! Split a subband into 4
416             void Split(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data);
417 
418             //! Create a single band from 4 quadrant bands
419             void Synth(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data);
420 
421            //! Return the value of the additional bitshift
GetShift()422             int GetShift() const {return 1;}
423 
424         };
425 
426         //! Class to do Haar wavelet filtering operations
427         class VHFilterHAAR0 : public VHFilter
428         {
429 
430         public:
431 
432             //! Split a subband into 4
433             void Split(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data);
434 
435             //! Create a single band from 4 quadrant bands
436             void Synth(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data);
437 
438            //! Return the value of the additional bitshift
GetShift()439             int GetShift() const {return 0;}
440 
441 
442         };
443 
444         //! Class to do Haar wavelet filtering operations with a single shift per level
445         class VHFilterHAAR1 : public VHFilter
446         {
447 
448         public:
449 
450             //! Split a subband into 4
451             void Split(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data);
452 
453             //! Create a single band from 4 quadrant bands
454             void Synth(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data);
455 
456            //! Return the value of the additional bitshift
GetShift()457             int GetShift() const {return 1;}
458 
459         };
460 
461 
462        //! Class to do Haar wavelet filtering operations with a double shift per level
463         class VHFilterHAAR2 : public VHFilter
464         {
465 
466         public:
467 
468             //! Split a subband into 4
469             void Split(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data);
470 
471             //! Create a single band from 4 quadrant bands
472             void Synth(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data);
473 
474             //! Return a correction factor to compensate for non-unity power gain of low-pass filter
GetLowFactor()475             double GetLowFactor() const { return 1.414213562;}
476 
477             //! Return a correction factor to compensate for non-unity power gain of high-pass filter
GetHighFactor()478             double GetHighFactor() const { return 0.707106781;}
479 
480             //! Return the value of the additional bitshift
GetShift()481             int GetShift() const {return 2;}
482 
483         };
484 
485 
486 
487         // Lifting steps used in the filters
488 
489         //! Class to do two-tap prediction lifting step
490         template<int shift>
491         class PredictStepShift
492         {
493 
494         public:
495 
496             //! Constructor
PredictStepShift()497             PredictStepShift(){}
498 
499             // Assume default copy constructor, assignment= and destructor //
500 
501             //! Do the filtering
502             /*
503                 Do the filtering.
504                 \param   in_val   the value being predicted
505                 \param   val1   the first value being used for prediction
506                 \param   val2   the second value being used for prediction
507             */
Filter(CoeffType & in_val,const CoeffType & val1,const CoeffType & val2)508             inline void Filter(CoeffType& in_val, const CoeffType& val1, const CoeffType& val2) const
509             {
510                 in_val -= (( val1 + val2 + (1<<(shift-1)) ) >>shift );
511             }
512 
513         };
514 
515         //! Class to do two-tap updating lifting step
516         template<int shift>
517         class UpdateStepShift
518         {
519 
520         public:
521             //! Constructor
UpdateStepShift()522             UpdateStepShift(){}
523 
524             //! Do the filtering
525             /*
526                 Do the filtering.
527                 \param   in_val   the value being updated
528                 \param   val1   the first value being used for updating
529                 \param   val2   the second value being used for updating
530             */
Filter(CoeffType & in_val,const CoeffType & val1,const CoeffType & val2)531             inline void Filter(CoeffType& in_val, const CoeffType& val1, const CoeffType& val2) const
532             {
533                 in_val += ( ( val1 + val2 + (1<<(shift-1)) ) >>shift );
534             }
535 
536         };
537 
538         //! Class to do symmetric four-tap prediction lifting step
539         template <int shift , int tap1, int tap2>
540         class PredictStepFourTap
541         {
542         public:
543 
544             //! Constructor
PredictStepFourTap()545             PredictStepFourTap(){}
546 
547             // Assume default copy constructor, assignment= and destructor //
548 
549             //! Do the filtering
Filter(CoeffType & in_val,const CoeffType & val1,const CoeffType & val2,const CoeffType & val3,const CoeffType & val4)550             inline void Filter(CoeffType& in_val, const CoeffType& val1, const CoeffType& val2 ,
551                                                   const CoeffType& val3, const CoeffType& val4 ) const
552             {
553                 in_val -= ( tap1*( val1 + val2 ) + tap2*( val3 + val4 ) + (1<<(shift-1)))>>shift;
554             }
555         };
556 
557         //! Class to do symmetric four-tap update lifting step
558         template <int shift , int tap1 , int tap2>
559         class UpdateStepFourTap
560         {
561 
562         public:
563             //! Constructor
UpdateStepFourTap()564             UpdateStepFourTap(){}
565 
566             //! Do the filtering
Filter(CoeffType & in_val,const CoeffType & val1,const CoeffType & val2,const CoeffType & val3,const CoeffType & val4)567             inline void Filter(CoeffType& in_val, const CoeffType& val1, const CoeffType& val2 ,
568                                                   const CoeffType& val3, const CoeffType& val4 ) const
569             {
570                 in_val += ( tap1*( val1 + val2 ) + tap2*( val3 + val4 ) + (1<<(shift-1)) )>>shift;
571             }
572         };
573 
574         //! Class to do two-tap prediction lifting step for Daubechies (9,7)
575         template <int gain> class PredictStep97
576         {
577         public:
578 
579             //! Constructor
PredictStep97()580             PredictStep97(){}
581 
582             // Assume default copy constructor, assignment= and destructor //
583 
584             //! Do the filtering
585             /*
586                 Do the filtering.
587                 \param   in_val   the value being predicted
588                 \param   val1   the first value being used for prediction
589                 \param   val2   the second value being used for prediction
590             */
Filter(CoeffType & in_val,const CoeffType & val1,const CoeffType & val2)591             inline void Filter(CoeffType& in_val, const CoeffType& val1, const CoeffType& val2) const
592             {
593                 in_val -= static_cast< CoeffType >( (gain * static_cast< int >( val1 + val2 )) >>12 );
594             }
595         };
596 
597         //! Class to do two-tap update lifting step for Daubechies (9,7)
598         template <int gain> class UpdateStep97
599         {
600 
601         public:
602             //! Constructor
UpdateStep97()603             UpdateStep97(){}
604 
605             //! Do the filtering
606             /*
607                 Do the filtering.
608                 \param   in_val   the value being updated
609                 \param   val1   the first value being used for updating
610                 \param   val2   the second value being used for updating
611             */
Filter(CoeffType & in_val,const CoeffType & val1,const CoeffType & val2)612             inline void Filter(CoeffType& in_val, const CoeffType& val1, const CoeffType& val2) const
613             {
614                 in_val += static_cast< CoeffType >( (gain * static_cast< int >( val1 + val2 )) >>12 );
615             }
616         };
617 
618     //! A class for wavelet coefficient data.
619     /*!
620         A class for encapsulating coefficient data, derived from TwoDArray..
621      */
622     class CoeffArray: public TwoDArray<CoeffType>
623     {
624     public:
625         //! Default constructor
626         /*!
627             Default constructor creates an empty array.
628         */
CoeffArray()629         CoeffArray(): TwoDArray<CoeffType>(){}
630 
631         //! Constructor.
632         /*!
633             Contructor creates a two-D array, with specified size and colour
634             format.
635         */
636         CoeffArray(int height, int width, CompSort cs=Y_COMP):
637             TwoDArray<CoeffType>(height, width), m_csort(cs){}
638 
639         //copy constructor and assignment= derived by inheritance
640 
641         //! Destructor
~CoeffArray()642         ~CoeffArray(){}
643 
644         //! Return which component is stored
CSort()645         const CompSort& CSort() const {return m_csort;}
646 
647         //! Set the type of component being stored
SetCSort(const CompSort cs)648         void SetCSort(const CompSort cs){ m_csort = cs; }
649 
650         //! Returns the set of subbands
BandList()651         SubbandList& BandList(){return m_band_list;}
652 
653         //! Returns the set of subbands
BandList()654         const SubbandList& BandList() const {return m_band_list;}
655 
656         //! Sets the subband weights
657         /*!
658             Sets perceptual weights for the subbands. Takes into account both perceptual factors
659             (weight noise less at higher spatial frequencies) and the scaling needed for the
660             wavelet transform.
661         */
662         void SetBandWeights (const EncoderParams& encparams,
663                                  const PictureParams& pparams,
664                                  const CompSort csort,
665 				 const float cpd_scale_factor);
666 
667         private:
668 
669         CompSort m_csort;
670 
671         // The subband list to be used for conventional transform apps
672         SubbandList m_band_list;
673 
674         private:
675 
676          //! Given x and y spatial frequencies in cycles per degree, returns a weighting value
677         float PerceptualWeight(float xf,float yf,CompSort cs);
678 
679     };
680 
681     //! A class to do wavelet transforms
682     /*!
683         A class to do forward and backward wavelet transforms by iteratively splitting or merging the
684         lowest frequency band.
685     */
686     class WaveletTransform
687     {
688     public:
689         //! Constructor
690         WaveletTransform(int d = 4, WltFilter f = DAUB9_7);
691 
692         //! Destructor
693         virtual ~WaveletTransform();
694 
695         //! Transforms the data to and from the wavelet domain
696         /*!
697             Transforms the data to and from the wavelet domain.
698             \param    d    the direction of the transform
699             \param    pic_data    the data to be transformed
700             \param    coeff_data  array that holds the transform coefficient data
701         */
702         void Transform(const Direction d, PicArray& pic_data, CoeffArray& coeff_data);
703 
704     private:
705 
706 
707     private:
708 
709         // Private variables
710 
711         //! Depth of the transform
712         int m_depth;
713 
714         //! The (vertical and horizontal) wavelet filter set to be used
715         WltFilter m_filt_sort;
716 
717         //! A class to do the vertical and horizontal filtering required
718         VHFilter* m_vhfilter;
719 
720     private:
721         // Private functions
722         //!    Private, bodyless copy constructor: class should not be copied
723         WaveletTransform(const WaveletTransform& cpy);
724 
725         //! Private, bodyless copy operator=: class should not be assigned
726         WaveletTransform& operator=(const WaveletTransform& rhs);
727 
728    };
729 }// end namespace dirac
730 
731 #endif
732