view liboctave/bsxfun-defs.cc @ 13983:7dd7cccf0757

clean up memory allocated for singletons before exit * singleton-cleanup.h, singleton-cleanup.cc: New files. * liboctave/Makefile.am (INCS, LIBOCTAVE_CXX_SOURCES): Add them to the lists. * toplev.cc (clean_up_and_exit): Call singleton_cleanup_list::cleanup. * debug.h, debug.cc (bp_table::instance_ok): Move definition to debug.cc. * coment-list.h (octave_comment_buffer::~octave_comment_buffer): Define destructor for class. * ov-typeinfo.h (octave_value_typeinfo::~octave_value_typeinfo): Likewise. * cmd-edit.h (command_editor::cleanup_instance): New function. * cmd-hist.h (command_history::cleanup_instance): New function. * file-ops.h (file_ops::cleanup_instance): New function. * mach-info.h (oct_mach_info::cleanup_instance): New function. * oct-env.h (octave_env::cleanup_instance): New function. * oct-fftw.h (octave_fftw_planner::cleanup_instance): New function. * oct-rand.h (octave_rand::cleanup_instance): New function. * oct-spparms.h (octave_sparse_params::cleanup_instance): New function. * pathsearch.h (static_members::cleanup_instance): New function. * comment-list.h (octave_comment_buffer::cleanup_instance): New function. * debug.h (bp_table::cleanup_instance): New function. * display.h (display_info::cleanup_instance): New function. * dynamic-ld.cc (octave_shlib_list::cleanup_instance, octave_mex_file_list::cleanup_instance): New functions. * dynamic-ld.h (octave_dynamic_loader::cleanup_instance): New function. * load-path.h (load_path::cleanup_instance): New function. * oct-stream.h (octave_stream_list::cleanup_instance): New function. * ov-typeinfo.h (octave_value_typeinfo::cleanup_instance): New function. * pager.h, pager.cc (octave_pager_stream::instance_ok, octave_pager_stream::cleanup_instance): New functions. (octave_diary_stream::instance_ok, octave_diary_stream::cleanup_instance): New functions. * sighandlers.h (octave_child_list::cleanup_instance): New function. * toplev.h (octave_call_stack * pager.cc (octave_pager_stream::stream, octave_diary_stream::stream): Use instance_ok to create instance. * toplev.h (octave_call_stack::cleanup_instance): New function. * cmd-edit.cc (command_editor::instance_ok): Register cleanup function. * cmd-hist.cc (command_history::instance_ok): Likewise. * file-ops.cc (file_ops::instance_ok): Likewise. * mach-info.cc (oct_mach_info::instance_ok): Likewise. * oct-env.cc (octave_env::instance_ok): Likewise. * oct-fftw.cc (octave_fftw_planner::instance_ok): Likewise. * oct-rand.cc (octave_rand::instance_ok): Likewise. * oct-spparms.cc (octave_sparse_params::instance_ok): Likewise. * pathsearch.cc (dir_path::static_members::instance_ok): Likewise. * comment-list.cc (comment_list::instance_ok): Likewise. * debug.cc (bp_table::instance_ok): Likewise. * display.cc (display_info::instance_ok): Likewise. * dynamic-ld.cc (octave_shlib_list::instance_ok, octave_mex_file_list::instance_ok, octave_dynamic_loader): Likewise. * load-path.cc (load_path::instance_ok): Likewise. * oct-stream.cc (octave_stream_list::instance_ok): Likewise. * ov-typeinfo.cc (octave_value_typeinfo::instance_ok): Likewise. * sighandlers.cc (octave_child_list::instance_ok): Likewise. * symtab.h, symtab.cc (symbol_table::scope_id::create_instance): New function. * symtab.h (symbol_table::scope_id::instance_ok): Call create_instance. * toplev.h, toplev.cc (octave_call_stack::create_instance): New function. * toplev.cc (octave_call_stack::instance_ok): Call create_instance. * pager.h, pager.cc (octave_pager_stream::set_diary_skip, octave_pager_stream::flush_current_contents_to_diary): Now static. octave_pager_stream::do_set_diary_skip, octave_pager_stream::do_flush_current_contents_to_diary): New functions. (octave_pager_stream::stream): Return std::ostream&, not octave_pager_stream&. If instance creation fails, return std::cout. (octave_diary_stream::stream): Return std::ostream&, not octave_diary_stream&. If instance creation fails, return std::cout. (octave_pager_stream::do_reset, octave_diary_stream::do_reset): Use instance_ok to create instance.
author John W. Eaton <jwe@octave.org>
date Sat, 03 Dec 2011 04:34:17 -0500
parents 6f779cc391fb
children 72c96de7a403
line wrap: on
line source

/*

Copyright (C) 2009-2011 Jaroslav Hajek
Copyright (C) 2009 VZLU Prague

This file is part of Octave.

Octave is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 3 of the License, or (at your
option) any later version.

Octave is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with Octave; see the file COPYING.  If not, see
<http://www.gnu.org/licenses/>.

*/

#if !defined (octave_bsxfun_defs_h)
#define octave_bsxfun_defs_h 1

#include <algorithm>
#include <iostream>

#include "dim-vector.h"
#include "oct-locbuf.h"
#include "lo-error.h"

#include "mx-inlines.cc"

template <class R, class X, class Y>
Array<R>
do_bsxfun_op (const Array<X>& x, const Array<Y>& y,
              void (*op_vv) (size_t, R *, const X *, const Y *),
              void (*op_sv) (size_t, R *, X, const Y *),
              void (*op_vs) (size_t, R *, const X *, Y))
{
  int nd = std::max (x.ndims (), y.ndims ());
  dim_vector dvx = x.dims ().redim (nd), dvy = y.dims ().redim (nd);

  // Construct the result dimensions.
  dim_vector dvr;
  dvr.resize (nd);
  for (int i = 0; i < nd; i++)
    {
      octave_idx_type xk = dvx(i), yk = dvy(i);
      if (xk == 1)
        dvr(i) = yk;
      else if (yk == 1 || xk == yk)
        dvr(i) = xk;
      else
        {
          (*current_liboctave_error_handler)
            ("bsxfun: nonconformant dimensions: %s and %s",
             x.dims ().str ().c_str (), y.dims ().str ().c_str ());
          break;
        }
    }

  Array<R> retval (dvr);

  const X *xvec = x.fortran_vec ();
  const Y *yvec = y.fortran_vec ();
  R *rvec = retval.fortran_vec ();

  // Fold the common leading dimensions.
  octave_idx_type start, ldr = 1;
  for (start = 0; start < nd; start++)
    {
      if (dvx(start) != dvy(start))
        break;
      ldr *= dvr(start);
    }

  if (retval.is_empty ())
    ; // do nothing
  else if (start == nd)
    op_vv (retval.numel (), rvec, xvec, yvec);
  else
    {
      // Determine the type of the low-level loop.
      bool xsing = false, ysing = false;
      if (ldr == 1)
        {
          xsing = dvx(start) == 1;
          ysing = dvy(start) == 1;
          if (xsing || ysing)
            {
              ldr *= dvx(start) * dvy(start);
              start++;
            }
        }
      dim_vector cdvx = dvx.cumulative (), cdvy = dvy.cumulative ();
      // Nullify singleton dims to achieve a spread effect.
      for (int i = std::max (start, octave_idx_type (1)); i < nd; i++)
        {
          if (dvx(i) == 1)
            cdvx(i-1) = 0;
          if (dvy(i) == 1)
            cdvy(i-1) = 0;
        }

      octave_idx_type niter = dvr.numel (start);
      // The index array.
      OCTAVE_LOCAL_BUFFER_INIT (octave_idx_type, idx, nd, 0);
      for (octave_idx_type iter = 0; iter < niter; iter++)
        {
          octave_quit ();

          // Compute indices.
          // FIXME: performance impact noticeable?
          octave_idx_type xidx = cdvx.cum_compute_index (idx);
          octave_idx_type yidx = cdvy.cum_compute_index (idx);
          octave_idx_type ridx = dvr.compute_index (idx);

          // Apply the low-level loop.
          if (xsing)
            op_sv (ldr, rvec + ridx, xvec[xidx], yvec + yidx);
          else if (ysing)
            op_vs (ldr, rvec + ridx, xvec + xidx, yvec[yidx]);
          else
            op_vv (ldr, rvec + ridx, xvec + xidx, yvec + yidx);

          dvr.increment_index (idx + start, start);
        }
    }

  return retval;
}

template <class R, class X>
void
do_inplace_bsxfun_op (Array<R>& r, const Array<X>& x,
                      void (*op_vv) (size_t, R *, const X *),
                      void (*op_vs) (size_t, R *, X))
{
  dim_vector dvr = r.dims (), dvx = x.dims ();
  octave_idx_type nd = r.ndims ();
  dvx.redim (nd);

  const X* xvec = x.fortran_vec ();
  R* rvec = r.fortran_vec ();

  // Fold the common leading dimensions.
  octave_idx_type start, ldr = 1;
  for (start = 0; start < nd; start++)
    {
      if (dvr(start) != dvx(start))
        break;
      ldr *= dvr(start);
    }

  if (r.is_empty ())
    ; // do nothing
  else if (start == nd)
    op_vv (r.numel (), rvec, xvec);
  else
    {
      // Determine the type of the low-level loop.
      bool xsing = false;
      if (ldr == 1)
        {
          xsing = dvx(start) == 1;
          if (xsing)
            {
              ldr *= dvr(start) * dvx(start);
              start++;
            }
        }

      dim_vector cdvx = dvx.cumulative ();
      // Nullify singleton dims to achieve a spread effect.
      for (int i = std::max (start, octave_idx_type (1)); i < nd; i++)
        {
          if (dvx(i) == 1)
            cdvx(i-1) = 0;
        }

      octave_idx_type niter = dvr.numel (start);
      // The index array.
      OCTAVE_LOCAL_BUFFER_INIT (octave_idx_type, idx, nd, 0);
      for (octave_idx_type iter = 0; iter < niter; iter++)
        {
          octave_quit ();

          // Compute indices.
          // FIXME: performance impact noticeable?
          octave_idx_type xidx = cdvx.cum_compute_index (idx);
          octave_idx_type ridx = dvr.compute_index (idx);

          // Apply the low-level loop.
          if (xsing)
            op_vs (ldr, rvec + ridx, xvec[xidx]);
          else
            op_vv (ldr, rvec + ridx, xvec + xidx);

          dvr.increment_index (idx + start, start);
        }
    }
}

#define BSXFUN_OP_DEF(OP, ARRAY) \
ARRAY bsxfun_ ## OP (const ARRAY& x, const ARRAY& y)

#define BSXFUN_OP2_DEF(OP, ARRAY, ARRAY1, ARRAY2) \
ARRAY bsxfun_ ## OP (const ARRAY1& x, const ARRAY2& y)

#define BSXFUN_REL_DEF(OP, ARRAY) \
boolNDArray bsxfun_ ## OP (const ARRAY& x, const ARRAY& y)

#define BSXFUN_OP_DEF_MXLOOP(OP, ARRAY, LOOP) \
  BSXFUN_OP_DEF(OP, ARRAY) \
  { return do_bsxfun_op<ARRAY::element_type, ARRAY::element_type, ARRAY::element_type> \
    (x, y, LOOP, LOOP, LOOP); }

#define BSXFUN_OP2_DEF_MXLOOP(OP, ARRAY, ARRAY1, ARRAY2, LOOP) \
  BSXFUN_OP2_DEF(OP, ARRAY, ARRAY1, ARRAY2) \
  { return do_bsxfun_op<ARRAY::element_type, ARRAY1::element_type, ARRAY2::element_type> \
    (x, y, LOOP, LOOP, LOOP); }

#define BSXFUN_REL_DEF_MXLOOP(OP, ARRAY, LOOP) \
  BSXFUN_REL_DEF(OP, ARRAY) \
  { return do_bsxfun_op<bool, ARRAY::element_type, ARRAY::element_type> \
    (x, y, LOOP, LOOP, LOOP); }

#define BSXFUN_STDOP_DEFS_MXLOOP(ARRAY) \
  BSXFUN_OP_DEF_MXLOOP (add, ARRAY, mx_inline_add) \
  BSXFUN_OP_DEF_MXLOOP (sub, ARRAY, mx_inline_sub) \
  BSXFUN_OP_DEF_MXLOOP (mul, ARRAY, mx_inline_mul) \
  BSXFUN_OP_DEF_MXLOOP (div, ARRAY, mx_inline_div) \
  BSXFUN_OP_DEF_MXLOOP (min, ARRAY, mx_inline_xmin) \
  BSXFUN_OP_DEF_MXLOOP (max, ARRAY, mx_inline_xmax) \

#define BSXFUN_STDREL_DEFS_MXLOOP(ARRAY) \
  BSXFUN_REL_DEF_MXLOOP (eq, ARRAY, mx_inline_eq) \
  BSXFUN_REL_DEF_MXLOOP (ne, ARRAY, mx_inline_ne) \
  BSXFUN_REL_DEF_MXLOOP (lt, ARRAY, mx_inline_lt) \
  BSXFUN_REL_DEF_MXLOOP (le, ARRAY, mx_inline_le) \
  BSXFUN_REL_DEF_MXLOOP (gt, ARRAY, mx_inline_gt) \
  BSXFUN_REL_DEF_MXLOOP (ge, ARRAY, mx_inline_ge)

//For bsxfun power with mixed integer/float types
#define BSXFUN_POW_MIXED_MXLOOP(INT_TYPE)                              \
  BSXFUN_OP2_DEF_MXLOOP (pow, INT_TYPE, INT_TYPE, NDArray, mx_inline_pow) \
  BSXFUN_OP2_DEF_MXLOOP (pow, INT_TYPE, INT_TYPE, FloatNDArray, mx_inline_pow)\
  BSXFUN_OP2_DEF_MXLOOP (pow, INT_TYPE, NDArray, INT_TYPE,  mx_inline_pow) \
  BSXFUN_OP2_DEF_MXLOOP (pow, INT_TYPE, FloatNDArray, INT_TYPE, mx_inline_pow)

#endif