Squashed 'kiwi/' content from commit 268028e

git-subtree-dir: kiwi
git-subtree-split: 268028ee4a694dcd89e4b1e683bf2f9ac48c08d9
This commit is contained in:
2024-02-11 15:32:50 -06:00
commit 81396a5322
76 changed files with 13184 additions and 0 deletions

338
py/src/solver.cpp Normal file
View File

@@ -0,0 +1,338 @@
/*-----------------------------------------------------------------------------
| Copyright (c) 2013-2019, Nucleic Development Team.
|
| Distributed under the terms of the Modified BSD License.
|
| The full license is in the file LICENSE, distributed with this software.
|----------------------------------------------------------------------------*/
#include <cppy/cppy.h>
#include <kiwi/kiwi.h>
#include "types.h"
#include "util.h"
namespace kiwisolver
{
namespace
{
PyObject*
Solver_new( PyTypeObject* type, PyObject* args, PyObject* kwargs )
{
if( PyTuple_GET_SIZE( args ) != 0 || ( kwargs && PyDict_Size( kwargs ) != 0 ) )
return cppy::type_error( "Solver.__new__ takes no arguments" );
PyObject* pysolver = PyType_GenericNew( type, args, kwargs );
if( !pysolver )
return 0;
Solver* self = reinterpret_cast<Solver*>( pysolver );
new( &self->solver ) kiwi::Solver();
return pysolver;
}
void
Solver_dealloc( Solver* self )
{
self->solver.~Solver();
Py_TYPE( self )->tp_free( pyobject_cast( self ) );
}
PyObject*
Solver_addConstraint( Solver* self, PyObject* other )
{
if( !Constraint::TypeCheck( other ) )
return cppy::type_error( other, "Constraint" );
Constraint* cn = reinterpret_cast<Constraint*>( other );
try
{
self->solver.addConstraint( cn->constraint );
}
catch( const kiwi::DuplicateConstraint& )
{
PyErr_SetObject( DuplicateConstraint, other );
return 0;
}
catch( const kiwi::UnsatisfiableConstraint& )
{
PyErr_SetObject( UnsatisfiableConstraint, other );
return 0;
}
Py_RETURN_NONE;
}
PyObject*
Solver_removeConstraint( Solver* self, PyObject* other )
{
if( !Constraint::TypeCheck( other ) )
return cppy::type_error( other, "Constraint" );
Constraint* cn = reinterpret_cast<Constraint*>( other );
try
{
self->solver.removeConstraint( cn->constraint );
}
catch( const kiwi::UnknownConstraint& )
{
PyErr_SetObject( UnknownConstraint, other );
return 0;
}
Py_RETURN_NONE;
}
PyObject*
Solver_hasConstraint( Solver* self, PyObject* other )
{
if( !Constraint::TypeCheck( other ) )
return cppy::type_error( other, "Constraint" );
Constraint* cn = reinterpret_cast<Constraint*>( other );
return cppy::incref( self->solver.hasConstraint( cn->constraint ) ? Py_True : Py_False );
}
PyObject*
Solver_addEditVariable( Solver* self, PyObject* args )
{
PyObject* pyvar;
PyObject* pystrength;
if( !PyArg_ParseTuple( args, "OO", &pyvar, &pystrength ) )
return 0;
if( !Variable::TypeCheck( pyvar ) )
return cppy::type_error( pyvar, "Variable" );
double strength;
if( !convert_to_strength( pystrength, strength ) )
return 0;
Variable* var = reinterpret_cast<Variable*>( pyvar );
try
{
self->solver.addEditVariable( var->variable, strength );
}
catch( const kiwi::DuplicateEditVariable& )
{
PyErr_SetObject( DuplicateEditVariable, pyvar );
return 0;
}
catch( const kiwi::BadRequiredStrength& e )
{
PyErr_SetString( BadRequiredStrength, e.what() );
return 0;
}
Py_RETURN_NONE;
}
PyObject*
Solver_removeEditVariable( Solver* self, PyObject* other )
{
if( !Variable::TypeCheck( other ) )
return cppy::type_error( other, "Variable" );
Variable* var = reinterpret_cast<Variable*>( other );
try
{
self->solver.removeEditVariable( var->variable );
}
catch( const kiwi::UnknownEditVariable& )
{
PyErr_SetObject( UnknownEditVariable, other );
return 0;
}
Py_RETURN_NONE;
}
PyObject*
Solver_hasEditVariable( Solver* self, PyObject* other )
{
if( !Variable::TypeCheck( other ) )
return cppy::type_error( other, "Variable" );
Variable* var = reinterpret_cast<Variable*>( other );
return cppy::incref( self->solver.hasEditVariable( var->variable ) ? Py_True : Py_False );
}
PyObject*
Solver_suggestValue( Solver* self, PyObject* args )
{
PyObject* pyvar;
PyObject* pyvalue;
if( !PyArg_ParseTuple( args, "OO", &pyvar, &pyvalue ) )
return 0;
if( !Variable::TypeCheck( pyvar ) )
return cppy::type_error( pyvar, "Variable" );
double value;
if( !convert_to_double( pyvalue, value ) )
return 0;
Variable* var = reinterpret_cast<Variable*>( pyvar );
try
{
self->solver.suggestValue( var->variable, value );
}
catch( const kiwi::UnknownEditVariable& )
{
PyErr_SetObject( UnknownEditVariable, pyvar );
return 0;
}
Py_RETURN_NONE;
}
PyObject*
Solver_updateVariables( Solver* self )
{
self->solver.updateVariables();
Py_RETURN_NONE;
}
PyObject*
Solver_reset( Solver* self )
{
self->solver.reset();
Py_RETURN_NONE;
}
PyObject*
Solver_dump( Solver* self )
{
cppy::ptr dump_str( PyUnicode_FromString( self->solver.dumps().c_str() ) );
PyObject_Print( dump_str.get(), stdout, 0 );
Py_RETURN_NONE;
}
PyObject*
Solver_dumps( Solver* self )
{
return PyUnicode_FromString( self->solver.dumps().c_str() );
}
static PyMethodDef
Solver_methods[] = {
{ "addConstraint", ( PyCFunction )Solver_addConstraint, METH_O,
"Add a constraint to the solver." },
{ "removeConstraint", ( PyCFunction )Solver_removeConstraint, METH_O,
"Remove a constraint from the solver." },
{ "hasConstraint", ( PyCFunction )Solver_hasConstraint, METH_O,
"Check whether the solver contains a constraint." },
{ "addEditVariable", ( PyCFunction )Solver_addEditVariable, METH_VARARGS,
"Add an edit variable to the solver." },
{ "removeEditVariable", ( PyCFunction )Solver_removeEditVariable, METH_O,
"Remove an edit variable from the solver." },
{ "hasEditVariable", ( PyCFunction )Solver_hasEditVariable, METH_O,
"Check whether the solver contains an edit variable." },
{ "suggestValue", ( PyCFunction )Solver_suggestValue, METH_VARARGS,
"Suggest a desired value for an edit variable." },
{ "updateVariables", ( PyCFunction )Solver_updateVariables, METH_NOARGS,
"Update the values of the solver variables." },
{ "reset", ( PyCFunction )Solver_reset, METH_NOARGS,
"Reset the solver to the initial empty starting condition." },
{ "dump", ( PyCFunction )Solver_dump, METH_NOARGS,
"Dump a representation of the solver internals to stdout." },
{ "dumps", ( PyCFunction )Solver_dumps, METH_NOARGS,
"Dump a representation of the solver internals to a string." },
{ 0 } // sentinel
};
static PyType_Slot Solver_Type_slots[] = {
{ Py_tp_dealloc, void_cast( Solver_dealloc ) }, /* tp_dealloc */
{ Py_tp_methods, void_cast( Solver_methods ) }, /* tp_methods */
{ Py_tp_new, void_cast( Solver_new ) }, /* tp_new */
{ Py_tp_alloc, void_cast( PyType_GenericAlloc ) }, /* tp_alloc */
{ Py_tp_free, void_cast( PyObject_Del ) }, /* tp_free */
{ 0, 0 },
};
} // namespace
// Initialize static variables (otherwise the compiler eliminates them)
PyTypeObject* Solver::TypeObject = NULL;
PyType_Spec Solver::TypeObject_Spec = {
"kiwisolver.Solver", /* tp_name */
sizeof( Solver ), /* tp_basicsize */
0, /* tp_itemsize */
Py_TPFLAGS_DEFAULT|
Py_TPFLAGS_BASETYPE, /* tp_flags */
Solver_Type_slots /* slots */
};
bool Solver::Ready()
{
// The reference will be handled by the module to which we will add the type
TypeObject = pytype_cast( PyType_FromSpec( &TypeObject_Spec ) );
if( !TypeObject )
{
return false;
}
return true;
}
PyObject* DuplicateConstraint;
PyObject* UnsatisfiableConstraint;
PyObject* UnknownConstraint;
PyObject* DuplicateEditVariable;
PyObject* UnknownEditVariable;
PyObject* BadRequiredStrength;
bool init_exceptions()
{
cppy::ptr mod( PyImport_ImportModule( "kiwisolver.exceptions" ) );
if( !mod )
{
return false;
}
DuplicateConstraint = mod.getattr( "DuplicateConstraint" );
if( !DuplicateConstraint )
{
return false;
}
UnsatisfiableConstraint = mod.getattr( "UnsatisfiableConstraint" );
if( !UnsatisfiableConstraint )
{
return false;
}
UnknownConstraint = mod.getattr( "UnknownConstraint" );
if( !UnknownConstraint )
{
return false;
}
DuplicateEditVariable = mod.getattr( "DuplicateEditVariable" );
if( !DuplicateEditVariable )
{
return false;
}
UnknownEditVariable = mod.getattr( "UnknownEditVariable" );
if( !UnknownEditVariable )
{
return false;
}
BadRequiredStrength = mod.getattr( "BadRequiredStrength" );
if( !BadRequiredStrength )
{
return false;
}
return true;
}
} // namespace