octave-bug-tracker
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Octave-bug-tracker] [bug #61800] possible code simplification with c++1


From: A.R. Burgers
Subject: [Octave-bug-tracker] [bug #61800] possible code simplification with c++17 std::variant
Date: Wed, 12 Jan 2022 04:38:24 -0500 (EST)
User-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:95.0) Gecko/20100101 Firefox/95.0

URL:
  <https://savannah.gnu.org/bugs/?61800>

                 Summary: possible code simplification with c++17 std::variant
                 Project: GNU Octave
            Submitted by: arb
            Submitted on: Wed 12 Jan 2022 09:38:22 AM UTC
                Category: Interpreter
                Severity: 3 - Normal
                Priority: 5 - Normal
              Item Group: Other
                  Status: None
             Assigned to: None
         Originator Name: 
        Originator Email: 
             Open/Closed: Open
                 Release: dev
         Discussion Lock: Any
        Operating System: Any

    _______________________________________________________

Details:

An octave_value by its nature can represent multiple types. This can lead to
convoluted code. To satisfy my own curiosity I had a look at std::variant to
see how that can help.

For instance in inv.cc for diagonal matrices: 


  if (arg.is_diag_matrix ())
    {
      rcond = 1.0;
      frcond = 1.0f;
      if (arg.iscomplex ())
        {
          if (isfloat)
            {
              result = arg.float_complex_diag_matrix_value ().inverse (info);
              if (info == -1)
                frcond = 0.0f;
              else if (nargout > 1)
                frcond = arg.float_complex_diag_matrix_value ().rcond ();
            }
          else
            {
              result = arg.complex_diag_matrix_value ().inverse (info);
              if (info == -1)
                rcond = 0.0;
              else if (nargout > 1)
                rcond = arg.complex_diag_matrix_value ().rcond ();
            }
        }
      else
        {
          if (isfloat)
            {
              result = arg.float_diag_matrix_value ().inverse (info);
              if (info == -1)
                frcond = 0.0f;
              else if (nargout > 1)
                frcond = arg.float_diag_matrix_value ().rcond ();
            }
          else
            {
              result = arg.diag_matrix_value ().inverse (info);
              if (info == -1)
                rcond = 0.0;
              else if (nargout > 1)
                rcond = arg.diag_matrix_value ().rcond ();
            }
        }
    }


Using std:variant this coding can easily be halved:


 if (arg.is_diag_matrix ())
    {
      rcond = 1.0;
      frcond = 1.0f;
      if (isfloat)
        {
          AnyDiag AD = arg.as_Any_fDiag ();
          result = std::visit([&info] (const auto &mat)->octave_value
                      {return mat.inverse (info);}, AD);
          if (info == -1)
            {
              frcond = 0.0f;
            }
          else if (nargout > 1)
            {
              frcond = std::visit([] (const auto &mat)->float
                      {return mat.rcond ();}, AD);
            }
        }
      else
        {
          AnyDiag AD = arg.as_Any_dDiag ();
          result = std::visit([&info] (const auto &mat)->octave_value
                      {return mat.inverse (info);}, AD);
          if (info == -1)
            {
              rcond = 0.0f;
            }
          else if (nargout > 1)
            {
              rcond = std::visit([] (const auto &mat)->double
                      {return mat.rcond ();}, AD);
            }
        }
    }


If the a condition number is not required, one could write pretty niftily:


      AnyDiag AD = arg.as_AnyDiag ();
      result = std::visit([&info] (const auto &mat)->octave_value
                      {return mat.inverse (info);}, AD);


The code to extract a diagonal matrix can be moved for reuse to the
octave_value class:


AnyDiag octave_value::as_Any_dDiag (void) {
  if (iscomplex ())
    return complex_diag_matrix_value ();
  else
    return diag_matrix_value ();
}

AnyDiag octave_value::as_Any_fDiag (void) {
  if (iscomplex ())
    return float_complex_diag_matrix_value ();
  else
    return float_diag_matrix_value ();
}

AnyDiag octave_value::as_AnyDiag (void) {
  bool isfloat = is_single_type ();
  if (iscomplex ())
    {
      if (isfloat)
        return float_complex_diag_matrix_value ();
      else
        return complex_diag_matrix_value ();
    }
  else
    {
      if (isfloat)
        return float_diag_matrix_value ();
      else
        return diag_matrix_value ();
    }
}


The std::variant typedefs in liboctave/array/AnyDiag.h are these:


#if ! defined (octave_AnyDiag_h)
#define octave_AnyDiag_h 1

#include "CDiagMatrix.h"
#include "dDiagMatrix.h"
#include "fCDiagMatrix.h"
#include "fDiagMatrix.h"
#include <variant>

typedef std::variant <     DiagMatrix,      ComplexDiagMatrix,
                      FloatDiagMatrix, FloatComplexDiagMatrix> AnyDiag;
typedef std::variant <     DiagMatrix,      ComplexDiagMatrix> Any_dDiag;
typedef std::variant <FloatDiagMatrix, FloatComplexDiagMatrix> Any_fDiag;

#endif // octave_AnyDiag_h                                                    
            


So it appears there is scope for code reduction and simplification, but it
requires c++-17, and I guess that makes it a bit of a long shot, as octave
doesn't seem to use features beyond c++-11.



    _______________________________________________________

File Attachments:


-------------------------------------------------------
Date: Wed 12 Jan 2022 09:38:22 AM UTC  Name: AnyDiag.cset  Size: 6KiB   By:
arb

<http://savannah.gnu.org/bugs/download.php?file_id=52649>

    _______________________________________________________

Reply to this item at:

  <https://savannah.gnu.org/bugs/?61800>

_______________________________________________
  Message sent via Savannah
  https://savannah.gnu.org/




reply via email to

[Prev in Thread] Current Thread [Next in Thread]