/[escript]/trunk/escript/src/Data.h
ViewVC logotype

Diff of /trunk/escript/src/Data.h

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 113 by jgs, Mon Feb 28 07:06:33 2005 UTC revision 149 by jgs, Thu Sep 1 03:31:39 2005 UTC
# Line 1  Line 1 
1  // $Id$  // $Id$
2  /*=============================================================================  /*
   
3   ******************************************************************************   ******************************************************************************
4   *                                                                            *   *                                                                            *
5   *       COPYRIGHT ACcESS 2004 -  All Rights Reserved                         *   *       COPYRIGHT ACcESS 2004 -  All Rights Reserved                         *
# Line 12  Line 11 
11   * person has a software license agreement with ACcESS.                       *   * person has a software license agreement with ACcESS.                       *
12   *                                                                            *   *                                                                            *
13   ******************************************************************************   ******************************************************************************
14    */
15    
16  ******************************************************************************/  /** \file Data.h */
17    
18  #ifndef DATA_H  #ifndef DATA_H
19  #define DATA_H  #define DATA_H
20    
21  #include "escript/Data/DataAbstract.h"  #include "escript/Data/DataAbstract.h"
22  #include "escript/Data/DataTagged.h"  #include "escript/Data/DataTagged.h"
23    #include "escript/Data/DataAlgorithm.h"
24  #include "escript/Data/FunctionSpace.h"  #include "escript/Data/FunctionSpace.h"
25  #include "escript/Data/BinaryOp.h"  #include "escript/Data/BinaryOp.h"
26  #include "escript/Data/UnaryOp.h"  #include "escript/Data/UnaryOp.h"
# Line 40  extern "C" { Line 41  extern "C" {
41  #include <boost/python/tuple.hpp>  #include <boost/python/tuple.hpp>
42  #include <boost/python/numeric.hpp>  #include <boost/python/numeric.hpp>
43    
44    namespace escript {
45    
46    //
47    // Forward declaration for various implementations of Data.
48    class DataEmpty;
49    class DataConstant;
50    class DataTagged;
51    class DataExpanded;
52    
53  /**  /**
54     \brief     \brief
55     Data is essentially a factory class which creates the appropriate Data     Data creates the appropriate Data object for the given construction
56     object for the given construction arguments. It retains control over     arguments.
    the object created for the lifetime of the object.  
    The type of Data object referred to may change during the lifetime of  
    the Data object.  
57    
58     Description:     Description:
59     Data is essentially a factory class which creates the appropriate Data     Data is essentially a factory class which creates the appropriate Data
# Line 55  extern "C" { Line 62  extern "C" {
62     The type of Data object referred to may change during the lifetime of     The type of Data object referred to may change during the lifetime of
63     the Data object.     the Data object.
64  */  */
   
 namespace escript {  
   
 //  
 // Forward declaration for various implimentations of Data.  
 class DataEmpty;  
 class DataConstant;  
 class DataTagged;  
 class DataExpanded;  
   
65  class Data {  class Data {
66    
67    public:    public:
# Line 223  class Data { Line 220  class Data {
220    
221    /**    /**
222       \brief       \brief
223         Return the values of all data-points as a single python numarray object.
224      */
225      const boost::python::numeric::array
226      convertToNumArray();
227    
228      /**
229         \brief
230         Return the values of all data-points for the given sample as a single python numarray object.
231      */
232      const boost::python::numeric::array
233      convertToNumArrayFromSampleNo(int sampleNo);
234    
235      /**
236         \brief
237         Return the value of the specified data-point as a single python numarray object.
238      */
239      const boost::python::numeric::array
240      convertToNumArrayFromDPNo(int sampleNo,
241                                int dataPointNo);
242    
243      /**
244         \brief
245         Fills the expanded Data object from values of a python numarray object.
246      */
247      void
248      fillFromNumArray(const boost::python::numeric::array);
249    
250      /**
251         \brief
252         Return the tag number associated with the given data-point.
253    
254         The data-point number here corresponds to the data-point number in the
255         numarray returned by convertToNumArray.
256      */
257      int
258      getTagNumber(int dpno);
259    
260      /**
261         \brief
262       Return the C wrapper for the Data object.       Return the C wrapper for the Data object.
263    */    */
264    escriptDataC    escriptDataC
# Line 464  class Data { Line 500  class Data {
500       \brief       \brief
501       Return the data point shape as a tuple of integers.       Return the data point shape as a tuple of integers.
502    */    */
503    boost::python::tuple    const boost::python::tuple
504    getShapeTuple() const;    getShapeTuple() const;
505    
506    /**    /**
# Line 501  class Data { Line 537  class Data {
537       cannot be converted to a DataTagged object.       cannot be converted to a DataTagged object.
538       \param tagKey - Input - Integer key.       \param tagKey - Input - Integer key.
539       \param value - Input - Value to associate with given key.       \param value - Input - Value to associate with given key.
      Note: removed for now - this version not needed, and breaks escript.cpp  
540    */    */
   /*  
541    void    void
542    setTaggedValue(int tagKey,    setTaggedValueFromCPP(int tagKey,
543                   const DataArrayView& value);                          const DataArrayView& value);
   */  
544    
545    /**    /**
546      \brief      \brief
# Line 525  class Data { Line 558  class Data {
558       \brief       \brief
559       Interpolates this onto the given functionspace and returns       Interpolates this onto the given functionspace and returns
560       the result as a Data object.       the result as a Data object.
561         *
562    */    */
563    Data    Data
564    interpolate(const FunctionSpace& functionspace) const;    interpolate(const FunctionSpace& functionspace) const;
# Line 533  class Data { Line 567  class Data {
567       \brief       \brief
568       Calculates the gradient of the data at the data points of functionspace.       Calculates the gradient of the data at the data points of functionspace.
569       If functionspace is not present the function space of Function(getDomain()) is used.       If functionspace is not present the function space of Function(getDomain()) is used.
570         *
571    */    */
572    Data    Data
573    gradOn(const FunctionSpace& functionspace) const;    gradOn(const FunctionSpace& functionspace) const;
# Line 543  class Data { Line 578  class Data {
578    /**    /**
579       \brief       \brief
580       Calculate the integral over the function space domain.       Calculate the integral over the function space domain.
581         *
582    */    */
583    boost::python::numeric::array    boost::python::numeric::array
584    integrate() const;    integrate() const;
# Line 550  class Data { Line 586  class Data {
586    /**    /**
587       \brief       \brief
588       Return a Data with a 1 for +ive values and a 0 for 0 or -ive values.       Return a Data with a 1 for +ive values and a 0 for 0 or -ive values.
589         *
590    */    */
591    Data    Data
592    wherePositive() const;    wherePositive() const;
# Line 557  class Data { Line 594  class Data {
594    /**    /**
595       \brief       \brief
596       Return a Data with a 1 for -ive values and a 0 for +ive or 0 values.       Return a Data with a 1 for -ive values and a 0 for +ive or 0 values.
597         *
598    */    */
599    Data    Data
600    whereNegative() const;    whereNegative() const;
# Line 564  class Data { Line 602  class Data {
602    /**    /**
603       \brief       \brief
604       Return a Data with a 1 for +ive or 0 values and a 0 for -ive values.       Return a Data with a 1 for +ive or 0 values and a 0 for -ive values.
605         *
606    */    */
607    Data    Data
608    whereNonNegative() const;    whereNonNegative() const;
# Line 571  class Data { Line 610  class Data {
610    /**    /**
611       \brief       \brief
612       Return a Data with a 1 for -ive or 0 values and a 0 for +ive values.       Return a Data with a 1 for -ive or 0 values and a 0 for +ive values.
613         *
614    */    */
615    Data    Data
616    whereNonPositive() const;    whereNonPositive() const;
# Line 578  class Data { Line 618  class Data {
618    /**    /**
619       \brief       \brief
620       Return a Data with a 1 for 0 values and a 0 for +ive or -ive values.       Return a Data with a 1 for 0 values and a 0 for +ive or -ive values.
621         *
622    */    */
623    Data    Data
624    whereZero() const;    whereZero() const;
# Line 585  class Data { Line 626  class Data {
626    /**    /**
627       \brief       \brief
628       Return a Data with a 0 for 0 values and a 1 for +ive or -ive values.       Return a Data with a 0 for 0 values and a 1 for +ive or -ive values.
629         *
630    */    */
631    Data    Data
632    whereNonZero() const;    whereNonZero() const;
633    
634    /**    /**
635       \brief       \brief
636       Return the sin of each data point of this Data object.       Return the maximum absolute value of this Data object.
637    */       *
   Data  
   sin() const;  
   
   /**  
      \brief  
      Return the cos of each data point of this Data object.  
   */  
   Data  
   cos() const;  
   
   /**  
      \brief  
      Return the tan of each data point of this Data object.  
   */  
   Data  
   tan() const;  
   
   /**  
      \brief  
      Return the log to base 10 of each data point of this Data object.  
   */  
   Data  
   log() const;  
   
   /**  
      \brief  
      Return the natural log of each data point of this Data object.  
638    */    */
639    Data    double
640    ln() const;    Lsup() const;
641    
642    /**    /**
643       \brief       \brief
644       Return the maximum absolute value of this Data object.       Return the minimum absolute value of this Data object.
645         *
646    */    */
647    double    double
648    Lsup() const;    Linf() const;
649    
650    /**    /**
651       \brief       \brief
652       Return the maximum value of this Data object.       Return the maximum value of this Data object.
653         *
654    */    */
655    double    double
656    sup() const;    sup() const;
# Line 641  class Data { Line 658  class Data {
658    /**    /**
659       \brief       \brief
660       Return the minimum value of this Data object.       Return the minimum value of this Data object.
661         *
662    */    */
663    double    double
664    inf() const;    inf() const;
# Line 648  class Data { Line 666  class Data {
666    /**    /**
667       \brief       \brief
668       Return the absolute value of each data point of this Data object.       Return the absolute value of each data point of this Data object.
669         *
670    */    */
671    Data    Data
672    abs() const;    abs() const;
# Line 655  class Data { Line 674  class Data {
674    /**    /**
675       \brief       \brief
676       Return the maximum value of each data point of this Data object.       Return the maximum value of each data point of this Data object.
677         *
678    */    */
679    Data    Data
680    maxval() const;    maxval() const;
# Line 662  class Data { Line 682  class Data {
682    /**    /**
683       \brief       \brief
684       Return the minimum value of each data point of this Data object.       Return the minimum value of each data point of this Data object.
685         *
686    */    */
687    Data    Data
688    minval() const;    minval() const;
689    
690    /**    /**
691       \brief       \brief
692         Return the (sample number, data-point number) of the data point with
693         the minimum value in this Data object.
694      */
695      const boost::python::tuple
696      mindp() const;
697    
698      void
699      calc_mindp(int& SampleNo,
700                 int& DataPointNo) const;
701    
702      /**
703         \brief
704       Return the length of each data point of this Data object.       Return the length of each data point of this Data object.
705       sqrt(sum(A[i,j,k,l]^2))       sqrt(sum(A[i,j,k,l]^2))
706         *
707    */    */
708    Data    Data
709    length() const;    length() const;
# Line 678  class Data { Line 712  class Data {
712       \brief       \brief
713       Return the sign of each data point of this Data object.       Return the sign of each data point of this Data object.
714       -1 for negative values, zero for zero values, 1 for positive values.       -1 for negative values, zero for zero values, 1 for positive values.
715         *
716    */    */
717    Data    Data
718    sign() const;    sign() const;
719    
720    /**    /**
721      \transpose       \brief
722      Transpose each data point of this Data object around the given axis.       Transpose each data point of this Data object around the given axis.
723      --* not implemented yet *--       --* not implemented yet *--
724         *
725    */    */
726    Data    Data
727    transpose(int axis) const;    transpose(int axis) const;
728    
729    /**    /**
730      \trace       \brief
731      Calculate the trace of each data point of this Data object.       Calculate the trace of each data point of this Data object.
732      sum(A[i,i,i,i])       sum(A[i,i,i,i])
733         *
734    */    */
735    Data    Data
736    trace() const;    trace() const;
737    
738    /**    /**
739      \exp       \brief
740      Return the exponential function of each data point of this Data object.       Return the sin of each data point of this Data object.
741         *
742    */    */
743    Data    Data
744    exp() const;    sin() const;
745    
746    /**    /**
747      \sqrt       \brief
748      Return the square root of each data point of this Data object.       Return the cos of each data point of this Data object.
749         *
750    */    */
751    Data    Data
752    sqrt() const;    cos() const;
753    
754    /**    /**
755       \brief       \brief
756       Return the given power of each data point of this Data object.       Return the tan of each data point of this Data object.
757         *
758    */    */
759    Data    Data
760    powD(const Data& right) const;    tan() const;
761    
762      /**
763         \brief
764         Return the log to base 10 of each data point of this Data object.
765         *
766      */
767    Data    Data
768    powO(const boost::python::object& right) const;    log() const;
769    
770    /**    /**
771      \brief       \brief
772      writes the object to a file in the DX file format       Return the natural log of each data point of this Data object.
773         *
774    */    */
775    void    Data
776    saveDX(std::string fileName) const;    ln() const;
777    
778    /**    /**
779      \brief       \brief
780      writes the object to a file in the VTK file format       Return the exponential function of each data point of this Data object.
781         *
782    */    */
783    void    Data
784    saveVTK(std::string fileName) const;    exp() const;
785    
786    /**    /**
787      \brief       \brief
788      Return the negation of each data point of this Data object.       Return the square root of each data point of this Data object.
789         *
790      */
791      Data
792      sqrt() const;
793    
794      /**
795         \brief
796         Return the negation of each data point of this Data object.
797         *
798    */    */
799    Data    Data
800    neg() const;    neg() const;
801    
802    /**    /**
803      \brief       \brief
804      Return the identity of each data point of this Data object.       Return the identity of each data point of this Data object.
805      Simply returns this object unmodified.       Simply returns this object unmodified.
806         *
807    */    */
808    Data    Data
809    pos() const;    pos() const;
810    
811    /**    /**
812       \brief       \brief
813         Return the given power of each data point of this Data object.
814    
815         \param right Input - the power to raise the object to.
816         *
817      */
818      Data
819      powD(const Data& right) const;
820    
821      /**
822         \brief
823         Return the given power of each data point of this boost python object.
824        
825         \param right Input - the power to raise the object to.
826         *
827       */
828      Data
829      powO(const boost::python::object& right) const;
830    
831      /**
832         \brief
833         writes the object to a file in the DX file format
834      */
835      void
836      saveDX(std::string fileName) const;
837    
838      /**
839         \brief
840         writes the object to a file in the VTK file format
841      */
842      void
843      saveVTK(std::string fileName) const;
844    
845      /**
846         \brief
847       Overloaded operator +=       Overloaded operator +=
848       \param right - Input - The right hand side.       \param right - Input - The right hand side.
849         *
850    */    */
851    Data& operator+=(const Data& right);    Data& operator+=(const Data& right);
852    Data& operator+=(const boost::python::object& right);    Data& operator+=(const boost::python::object& right);
# Line 763  class Data { Line 855  class Data {
855       \brief       \brief
856       Overloaded operator -=       Overloaded operator -=
857       \param right - Input - The right hand side.       \param right - Input - The right hand side.
858         *
859    */    */
860    Data& operator-=(const Data& right);    Data& operator-=(const Data& right);
861    Data& operator-=(const boost::python::object& right);    Data& operator-=(const boost::python::object& right);
# Line 771  class Data { Line 864  class Data {
864       \brief       \brief
865       Overloaded operator *=       Overloaded operator *=
866       \param right - Input - The right hand side.       \param right - Input - The right hand side.
867         *
868    */    */
869    Data& operator*=(const Data& right);    Data& operator*=(const Data& right);
870    Data& operator*=(const boost::python::object& right);    Data& operator*=(const boost::python::object& right);
# Line 779  class Data { Line 873  class Data {
873       \brief       \brief
874       Overloaded operator /=       Overloaded operator /=
875       \param right - Input - The right hand side.       \param right - Input - The right hand side.
876         *
877    */    */
878    Data& operator/=(const Data& right);    Data& operator/=(const Data& right);
879    Data& operator/=(const boost::python::object& right);    Data& operator/=(const boost::python::object& right);
# Line 812  class Data { Line 907  class Data {
907       \brief       \brief
908       Copies slice from value into this Data object.       Copies slice from value into this Data object.
909    
      \description  
910       Implements the [] set operator in python.       Implements the [] set operator in python.
911       Calls setSlice.       Calls setSlice.
912    
# Line 845  class Data { Line 939  class Data {
939       Return a Data object containing the specified slice of       Return a Data object containing the specified slice of
940       this Data object.       this Data object.
941       \param region - Input - Region to copy.       \param region - Input - Region to copy.
942         *
943    */    */
944    Data    Data
945    getSlice(const DataArrayView::RegionType& region) const;    getSlice(const DataArrayView::RegionType& region) const;
# Line 855  class Data { Line 950  class Data {
950       Data object.       Data object.
951       \param value - Input - Data to copy from.       \param value - Input - Data to copy from.
952       \param region - Input - Region to copy.       \param region - Input - Region to copy.
953         *
954    */    */
955    void    void
956    setSlice(const Data& value,    setSlice(const Data& value,
957             const DataArrayView::RegionType& region);             const DataArrayView::RegionType& region);
958    
959      /**
960         \brief
961         Archive the current Data object to the given file.
962         \param fileName - Input - file to archive to.
963      */
964      void
965      archiveData(const std::string fileName);
966    
967      /**
968         \brief
969         Extract the Data object archived in the given file, overwriting
970         the current Data object.
971         Note - the current object must be of type DataEmpty.
972         \param fileName - Input - file to extract from.
973         \param fspace - Input - a suitable FunctionSpace descibing the data.
974      */
975      void
976      extractData(const std::string fileName,
977                  const FunctionSpace& fspace);
978    
979   protected:   protected:
980    
981   private:   private:
# Line 882  class Data { Line 998  class Data {
998       Perform the specified reduction algorithm on every element of every data point in       Perform the specified reduction algorithm on every element of every data point in
999       this Data object according to the given function and return the single value result.       this Data object according to the given function and return the single value result.
1000    */    */
1001    template <class UnaryFunction>    template <class BinaryFunction>
1002    inline    inline
1003    double    double
1004    algorithm(UnaryFunction operation) const;    algorithm(BinaryFunction operation,
1005                double initial_value) const;
1006    
1007    /**    /**
1008       \brief       \brief
# Line 894  class Data { Line 1011  class Data {
1011       one value - the result of the reduction operation on the corresponding data-point in       one value - the result of the reduction operation on the corresponding data-point in
1012       this Data object       this Data object
1013    */    */
1014    template <class UnaryFunction>    template <class BinaryFunction>
1015    inline    inline
1016    Data    Data
1017    dp_algorithm(UnaryFunction operation) const;    dp_algorithm(BinaryFunction operation,
1018                   double initial_value) const;
1019    
1020    /**    /**
1021       \brief       \brief
# Line 964  class Data { Line 1082  class Data {
1082    // pointer to the actual data object    // pointer to the actual data object
1083    boost::shared_ptr<DataAbstract> m_data;    boost::shared_ptr<DataAbstract> m_data;
1084    
1085      //
1086      // pointer to the internal profiling data
1087      struct profDataEntry *profData;
1088    
1089  };  };
1090    
1091  template <class IValueType>  template <class IValueType>
# Line 1259  Data::unaryOp(UnaryFunction operation) Line 1381  Data::unaryOp(UnaryFunction operation)
1381    object (*this) is a rank n Data object, and returned object is a scalar.    object (*this) is a rank n Data object, and returned object is a scalar.
1382    Calls escript::algorithm.    Calls escript::algorithm.
1383  */  */
1384  template <class UnaryFunction>  template <class BinaryFunction>
1385  inline  inline
1386  double  double
1387  Data::algorithm(UnaryFunction operation) const  Data::algorithm(BinaryFunction operation, double initial_value) const
1388  {  {
1389    if (isExpanded()) {    if (isExpanded()) {
1390      DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get());      DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get());
1391      EsysAssert((leftC!=0), "Programming error - casting to DataExpanded.");      EsysAssert((leftC!=0), "Programming error - casting to DataExpanded.");
1392      return escript::algorithm(*leftC,operation);      return escript::algorithm(*leftC,operation,initial_value);
1393    } else if (isTagged()) {    } else if (isTagged()) {
1394      DataTagged* leftC=dynamic_cast<DataTagged*>(m_data.get());      DataTagged* leftC=dynamic_cast<DataTagged*>(m_data.get());
1395      EsysAssert((leftC!=0), "Programming error - casting to DataTagged.");      EsysAssert((leftC!=0), "Programming error - casting to DataTagged.");
1396      return escript::algorithm(*leftC,operation);      return escript::algorithm(*leftC,operation,initial_value);
1397    } else if (isConstant()) {    } else if (isConstant()) {
1398      DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());      DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());
1399      EsysAssert((leftC!=0), "Programming error - casting to DataConstant.");      EsysAssert((leftC!=0), "Programming error - casting to DataConstant.");
1400      return escript::algorithm(*leftC,operation);      return escript::algorithm(*leftC,operation,initial_value);
1401    }    }
1402    return 0;    return 0;
1403  }  }
# Line 1288  Data::algorithm(UnaryFunction operation) Line 1410  Data::algorithm(UnaryFunction operation)
1410    rank 0 Data object.    rank 0 Data object.
1411    Calls escript::dp_algorithm.    Calls escript::dp_algorithm.
1412  */  */
1413  template <class UnaryFunction>  template <class BinaryFunction>
1414  inline  inline
1415  Data  Data
1416  Data::dp_algorithm(UnaryFunction operation) const  Data::dp_algorithm(BinaryFunction operation, double initial_value) const
1417  {  {
1418    Data result(0,DataArrayView::ShapeType(),getFunctionSpace(),isExpanded());    Data result(0,DataArrayView::ShapeType(),getFunctionSpace(),isExpanded());
1419    if (isExpanded()) {    if (isExpanded()) {
# Line 1299  Data::dp_algorithm(UnaryFunction operati Line 1421  Data::dp_algorithm(UnaryFunction operati
1421      DataExpanded* resultE=dynamic_cast<DataExpanded*>(result.m_data.get());      DataExpanded* resultE=dynamic_cast<DataExpanded*>(result.m_data.get());
1422      EsysAssert((dataE!=0), "Programming error - casting data to DataExpanded.");      EsysAssert((dataE!=0), "Programming error - casting data to DataExpanded.");
1423      EsysAssert((resultE!=0), "Programming error - casting result to DataExpanded.");      EsysAssert((resultE!=0), "Programming error - casting result to DataExpanded.");
1424      escript::dp_algorithm(*dataE,*resultE,operation);      escript::dp_algorithm(*dataE,*resultE,operation,initial_value);
1425    } else if (isTagged()) {    } else if (isTagged()) {
1426      DataTagged* dataT=dynamic_cast<DataTagged*>(m_data.get());      DataTagged* dataT=dynamic_cast<DataTagged*>(m_data.get());
1427      DataTagged* resultT=dynamic_cast<DataTagged*>(result.m_data.get());      DataTagged* resultT=dynamic_cast<DataTagged*>(result.m_data.get());
1428      EsysAssert((dataT!=0), "Programming error - casting data to DataTagged.");      EsysAssert((dataT!=0), "Programming error - casting data to DataTagged.");
1429      EsysAssert((resultT!=0), "Programming error - casting result to DataTagged.");      EsysAssert((resultT!=0), "Programming error - casting result to DataTagged.");
1430      escript::dp_algorithm(*dataT,*resultT,operation);      escript::dp_algorithm(*dataT,*resultT,operation,initial_value);
1431    } else if (isConstant()) {    } else if (isConstant()) {
1432      DataConstant* dataC=dynamic_cast<DataConstant*>(m_data.get());      DataConstant* dataC=dynamic_cast<DataConstant*>(m_data.get());
1433      DataConstant* resultC=dynamic_cast<DataConstant*>(result.m_data.get());      DataConstant* resultC=dynamic_cast<DataConstant*>(result.m_data.get());
1434      EsysAssert((dataC!=0), "Programming error - casting data to DataConstant.");      EsysAssert((dataC!=0), "Programming error - casting data to DataConstant.");
1435      EsysAssert((resultC!=0), "Programming error - casting result to DataConstant.");      EsysAssert((resultC!=0), "Programming error - casting result to DataConstant.");
1436      escript::dp_algorithm(*dataC,*resultC,operation);      escript::dp_algorithm(*dataC,*resultC,operation,initial_value);
1437    }    }
1438    return result;    return result;
1439  }  }

Legend:
Removed from v.113  
changed lines
  Added in v.149

  ViewVC Help
Powered by ViewVC 1.1.26