Skip to content

Commit

Permalink
Put members into parameter map with SG_ADD
Browse files Browse the repository at this point in the history
- Fix nasty bug in non-owning any policy causing
  everything to crash badly
- Add lib/equals to check whether objects are equal
  and implement it for required classes
- Add unit-tests to check it is working properly
  • Loading branch information
lisitsyn committed Aug 6, 2016
1 parent b5b3cbf commit b7823b9
Show file tree
Hide file tree
Showing 9 changed files with 354 additions and 53 deletions.
9 changes: 9 additions & 0 deletions src/shogun/base/SGObject.h
Expand Up @@ -69,12 +69,14 @@ template <class T> class SGStringList;

#define SG_ADD4(param, name, description, ms_available) {\
m_parameters->add(param, name, description);\
register_member(name, param);\
if (ms_available)\
m_model_selection_parameters->add(param, name, description);\
}

#define SG_ADD5(param, name, description, ms_available, gradient_available) {\
m_parameters->add(param, name, description);\
register_member(name, param);\
if (ms_available)\
m_model_selection_parameters->add(param, name, description);\
if (gradient_available)\
Expand Down Expand Up @@ -455,6 +457,13 @@ class CSGObject
set_with_base_tag(tag, erase_type(value));
}

template <typename T>
void register_member(const std::string& name, T* pointer)
{
BaseTag tag(name);
set_with_base_tag(tag, Any::non_owning(pointer));
}

public:
/** Updates the hash of current parameter combination */
virtual void update_parameter_hash();
Expand Down
8 changes: 8 additions & 0 deletions src/shogun/lib/SGMatrix.h
Expand Up @@ -15,6 +15,7 @@

#include <shogun/lib/config.h>
#include <shogun/lib/common.h>
#include <shogun/lib/equals.h>
#include <shogun/lib/SGReferencedData.h>

namespace Eigen
Expand Down Expand Up @@ -375,5 +376,12 @@ template<class T> class SGMatrix : public SGReferencedData
/** number of columns of matrix */
index_t num_cols;
};

template <typename S>
bool equals(SGMatrix<S>* lhs, SGMatrix<S>* rhs)
{
return lhs->equals(*rhs);
}

}
#endif // __SGMATRIX_H__
8 changes: 8 additions & 0 deletions src/shogun/lib/SGSparseVector.h
Expand Up @@ -19,6 +19,8 @@
#include <shogun/lib/SGReferencedData.h>
#include <shogun/lib/SGVector.h>

#include <stdexcept>

namespace shogun
{
class CFile;
Expand Down Expand Up @@ -216,6 +218,12 @@ template <class T> class SGSparseVector : public SGReferencedData

};

template <typename S>
bool equals(SGSparseVector<S>* lhs, SGSparseVector<S>* rhs)
{
throw std::logic_error("Equals not supported by SGSparseVector");
}

}

#endif // __SGSPARSEVECTOR_H__
7 changes: 7 additions & 0 deletions src/shogun/lib/SGVector.h
Expand Up @@ -17,6 +17,7 @@
#include <shogun/lib/config.h>

#include <shogun/lib/common.h>
#include <shogun/lib/equals.h>
#include <shogun/lib/SGReferencedData.h>

namespace Eigen
Expand Down Expand Up @@ -492,6 +493,12 @@ template<class T> class SGVector : public SGReferencedData
index_t vlen;
};

template <typename S>
bool equals(SGVector<S>* lhs, SGVector<S>* rhs)
{
return lhs->equals(*rhs);
}

#ifndef DOXYGEN_SHOULD_SKIP_THIS
template<> void SGVector<float64_t>::vec1_plus_scalar_times_vec2(float64_t* vec1,
const float64_t scalar, const float64_t* vec2, int32_t n);
Expand Down
101 changes: 69 additions & 32 deletions src/shogun/lib/any.h
Expand Up @@ -35,13 +35,34 @@
#ifndef _ANY_H_
#define _ANY_H_

#include <shogun/lib/equals.h>

#include <string.h>
#include <stdexcept>
#include <typeinfo>
#include <cxxabi.h>

namespace shogun
{

/** Empty object. Used by @ref Any to store nothing.
*/
struct Empty
{
};

/** Equality function for @ref Empty. Always returns
* true as empty objects are all equal.
*
* @param lhs first object
* @param rhs second object
*/
template <>
inline bool equals(Empty* lhs, Empty* rhs)
{
return true;
}

/** Converts compiler-dependent name of class to
* something human readable.
* @return human readable name of class
Expand Down Expand Up @@ -71,7 +92,7 @@ namespace shogun
* @param v pointer to value
*/
virtual void set(void** storage, const void* v) const = 0;

/** Clears storage.
* @param storage pointer to a pointer to storage
*/
Expand All @@ -88,12 +109,18 @@ namespace shogun
*/
virtual bool matches(const std::type_info& ti) const = 0;

/** Returns type info.
*
* @return information about underlying type
*/
virtual const std::type_info& type_info() const = 0;

/** Compares two storages.
* @param storage pointer to a pointer to storage
* @param other_storage pointer to a pointer to another storage
* @return true if both storages have same value
*/
virtual bool equals(void** storage, void** other_storage) const = 0;
virtual bool are_equal(void** storage, void** other_storage) const = 0;
};

/** @brief This implementation of @ref BaseAnyPolicy uses external
Expand All @@ -110,7 +137,7 @@ namespace shogun
*/
virtual void set(void** storage, const void* v) const
{
*(reinterpret_cast<T*>(storage)) = *reinterpret_cast<T const*>(v);
*(reinterpret_cast<T*>(*storage)) = *reinterpret_cast<T const*>(v);
}

/** Clears storage. In this case does nothing as storage
Expand Down Expand Up @@ -144,11 +171,20 @@ namespace shogun
* @param other_storage pointer to a pointer to another storage
* @return true if both storages have same value
*/
bool equals(void** storage, void** other_storage) const
bool are_equal(void** storage, void** other_storage) const
{
T* typed_storage = (reinterpret_cast<T*>(*storage));
T* typed_other_storage = (reinterpret_cast<T*>(*other_storage));
return equals(typed_storage, typed_other_storage);
}

/** Returns type info.
*
* @return information about underlying type
*/
virtual const std::type_info& type_info() const
{
T typed_storage = *(reinterpret_cast<T*>(*storage));
T typed_other_storage = *(reinterpret_cast<T*>(*other_storage));
return typed_storage == typed_other_storage;
return typeid(T);
}
};

Expand All @@ -167,7 +203,7 @@ namespace shogun
{
*(storage) = new T(*reinterpret_cast<T const*>(v));
}

/** Clears storage.
* @param storage pointer to a pointer to storage
*/
Expand Down Expand Up @@ -198,11 +234,20 @@ namespace shogun
* @param other_storage pointer to a pointer to another storage
* @return true if both storages have same value
*/
bool equals(void** storage, void** other_storage) const
bool are_equal(void** storage, void** other_storage) const
{
T* typed_storage = (reinterpret_cast<T*>(*storage));
T* typed_other_storage = (reinterpret_cast<T*>(*other_storage));
return equals(typed_storage, typed_other_storage);
}

/** Returns type info.
*
* @return information about underlying type
*/
virtual const std::type_info& type_info() const
{
T typed_storage = *(reinterpret_cast<T*>(*storage));
T typed_other_storage = *(reinterpret_cast<T*>(*other_storage));
return typed_storage == typed_other_storage;
return typeid(T);
}
};

Expand All @@ -216,18 +261,23 @@ namespace shogun
{
public:
/** Used to denote an empty Any object */
struct Empty;

/** Constructor */
Any() : policy(default_policy<Empty>()), storage(nullptr)
{
}

/** Creates an instance from raw pointer
* in non-owning fashion. The pointer will be used
* by @ref Any and will never be deleted.
*
* @param raw_ptr pointer to use
*/
template <typename T>
static Any non_owning(T* raw_ptr) {
Any any;
any.policy = non_owning_policy<T>();
any.storage = raw_ptr;
any.storage = static_cast<void*>(raw_ptr);
return any;
}

Expand All @@ -238,20 +288,17 @@ namespace shogun
policy->set(&storage, &v);
}

/** Copy constructor */
Any(const Any& other) : policy(other.policy), storage(nullptr)
{
policy->set(&storage, other.storage);
}

/** Assignment operator
* @param other another Any object
* @return Any object
*/
Any& operator=(const Any& other)
{
policy->clear(&storage);
policy = other.policy;
if (not policy->matches(other.policy->type_info())) {
policy = other.policy;
storage = other.storage;
}
policy->set(&storage, other.storage);
return *(this);
}
Expand Down Expand Up @@ -338,24 +385,14 @@ namespace shogun
void* lhs_storage = lhs.storage;
void* rhs_storage = rhs.storage;
return lhs.policy == rhs.policy and
lhs.policy->equals(&lhs_storage, &rhs_storage);
lhs.policy->are_equal(&lhs_storage, &rhs_storage);
}

inline bool operator!=(const Any& lhs, const Any& rhs)
{
return !(lhs == rhs);
}

/** Used to denote an empty Any object */
struct Any::Empty
{
/** Equality operator */
bool operator==(const Empty& other) const
{
return true;
}
};

/** Erases value type i.e. converts it to Any
* For input object of any type, it returns an Any object
* which stores the input object's raw value. It saves the type
Expand Down
78 changes: 78 additions & 0 deletions src/shogun/lib/equals.cpp
@@ -0,0 +1,78 @@
/*
* Copyright (c) 2016, Shogun-Toolbox e.V. <shogun-team@shogun-toolbox.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Written (W) 2016 Sergey Lisitsyn
*/

#include <shogun/lib/common.h>
#include <shogun/lib/equals.h>

#include <shogun/base/SGObject.h>
#include <shogun/kernel/Kernel.h>

namespace shogun
{
#define BASIC_EQUALS(type) \
template <> \
bool equals(type* lhs, type* rhs) \
{ \
return *lhs == *rhs; \
}

BASIC_EQUALS(bool);
BASIC_EQUALS(char);
BASIC_EQUALS(int8_t);
BASIC_EQUALS(uint8_t);
BASIC_EQUALS(int16_t);
BASIC_EQUALS(uint16_t);
BASIC_EQUALS(int32_t);
BASIC_EQUALS(uint32_t);
BASIC_EQUALS(int64_t);
BASIC_EQUALS(uint64_t);
BASIC_EQUALS(float32_t);
BASIC_EQUALS(float64_t);
BASIC_EQUALS(floatmax_t);
BASIC_EQUALS(complex128_t);

template <>
bool equals(CSGObject** lhs, CSGObject** rhs)
{
return (*lhs)->equals(*rhs);
}

template <>
bool equals(CKernel** lhs, CKernel** rhs)
{
return (*lhs)->equals(*rhs);
}

}

#undef BASIC_EQUALS

0 comments on commit b7823b9

Please sign in to comment.