Commit 034da510 authored by Berk Onat's avatar Berk Onat
Browse files

Changed C API Numpy library to directly access molfile structure data

parent 672baac3
import numpy
import ctypes
import _libpymolfile
class molatom_t(ctypes.Structure):
_fields_ = [
('name', ctypes.c_char * 16),
('type', ctypes.c_char * 16),
('resname', ctypes.c_char * 8),
('resid', ctypes.c_uint8),
('segid', ctypes.c_char * 8),
('chain', ctypes.c_char * 2),
('altloc', ctypes.c_char * 2),
('insertion', ctypes.c_char *2),
('occupancy', ctypes.c_float),
('bfactor', ctypes.c_float),
('mass', ctypes.c_float),
('charge', ctypes.c_float),
('radius', ctypes.c_float),
('atomicnumber', ctypes.c_uint8),
('ctnumber', ctypes.c_uint8),
]
class molplugin_t(ctypes.Structure):
_fields_ = [
('abiversion', ctypes.c_uint8),
('type', ctypes.c_char_p),
('name', ctypes.c_char_p),
('prettyname', ctypes.c_char_p),
('author', ctypes.c_char_p),
('majorv', ctypes.c_uint8),
('minorv', ctypes.c_uint8),
('is_reentrant', ctypes.c_uint8),
('filename_extension', ctypes.c_char_p),
('open_file_read', ctypes.CFUNCTYPE(ctypes.c_char_p,
ctypes.c_char_p, ctypes.POINTER(ctypes.c_uint8))),
('read_structure', ctypes.CFUNCTYPE(ctypes.c_void_p,
ctypes.POINTER(ctypes.c_uint), ctypes.POINTER(molatom_t))),
('read_bonds', ctypes.CFUNCTYPE(ctypes.c_void_p,
ctypes.POINTER(ctypes.c_uint), ctypes.POINTER(ctypes.c_uint), ctypes.POINTER(ctypes.c_uint),
ctypes.POINTER(ctypes.c_float), ctypes.POINTER(ctypes.c_uint), ctypes.POINTER(ctypes.c_uint),
ctypes.c_char_p)),
('read_next_timestep', ctypes.c_int8),
('close_file_read', ctypes.c_void_p),
('open_file_write', ctypes.c_void_p),
('write_structure', ctypes.c_int8),
('write_timestep', ctypes.c_int8),
('close_file_write', ctypes.c_void_p),
('read_volumetric_metadata', ctypes.c_int8),
('read_volumetric_data', ctypes.c_int8),
('read_volumetric_data_ex', ctypes.c_int8),
('read_rawgraphics', ctypes.c_int8),
('read_molecule_metadata', ctypes.c_int8),
('write_bonds', ctypes.c_int8),
('write_volumetric_data', ctypes.c_int8),
('write_volumetric_data_ex', ctypes.c_int8),
('read_angles', ctypes.c_int8),
('write_angles', ctypes.c_int8),
('read_qm_metadata', ctypes.c_int8),
('read_qm_rundata', ctypes.c_int8),
('read_timestep', ctypes.c_int8),
('read_timestep_metadata', ctypes.c_int8),
('read_qm_timestep_metadata', ctypes.c_int8),
('read_timestep2', ctypes.c_int8),
('read_times', ctypes.c_ssize_t),
('cons_fputs', ctypes.c_uint8)
]
class moltimestep_t(ctypes.Structure):
_fields_ = [
('coords', ctypes.POINTER(ctypes.c_float)),
('velocities', ctypes.POINTER(ctypes.c_float)),
('A', ctypes.c_float),
('B', ctypes.c_float),
('C', ctypes.c_float),
('alpha', ctypes.c_float),
('beta', ctypes.c_float),
('gamma', ctypes.c_float),
('physical_time', ctypes.c_double),
('total_energy', ctypes.c_double),
('potential_energy', ctypes.c_double),
('kinetic_energy', ctypes.c_double),
('extended_energy', ctypes.c_double),
('force_energy', ctypes.c_double),
('total_pressure', ctypes.c_double)
]
class molhandle_t(ctypes.Structure):
_fields_ = [
('plugin', ctypes.POINTER(molplugin_t)),
('file_handle', ctypes.c_void_p),
('natoms', ctypes.c_int)
]
class molnatoms(ctypes.Structure):
_fields_ = [
('natoms', ctypes.c_int)
]
#callback_t = ctypes.CFUNCTYPE(None, ctypes.POINTER(molatom_t))
def get_open_file_read(output):
ctypes.open_file_read.restype = ctypes.POINTER(molhandle_t)
ctypes.open_file_read.argtypes = [ctypes.POINTER(molplugin_t), ctypes.c_void_p, ctypes.c_uint8]
return ctypes.pythonapi.PyCapsule_GetPointer(output, "plugin")
def get_capsule(capsule):
ctypes.pythonapi.PyCapsule_GetPointer.restype = ctypes.c_void_p
ctypes.pythonapi.PyCapsule_GetPointer.argtypes = [ctypes.py_object, ctypes.c_char_p]
return ctypes.pythonapi.PyCapsule_GetPointer(capsule, b"plugin")
def get_plugincapsule(capsule):
data = ctypes.POINTER(molhandle_t)
ctypes.pythonapi.PyCapsule_GetPointer.restype = ctypes.POINTER(molhandle_t)
ctypes.pythonapi.PyCapsule_GetPointer.argtypes = [ctypes.py_object, ctypes.c_char_p]
data = ctypes.pythonapi.PyCapsule_GetPointer(capsule, b"plugin")
return data
def get_plugindata(capsule):
data = ctypes.POINTER(molhandle_t)
ctypes.pythonapi.PyCapsule_GetPointer.restype = ctypes.POINTER(molhandle_t)
ctypes.pythonapi.PyCapsule_GetPointer.argtypes = [ctypes.py_object, ctypes.c_char_p]
data = ctypes.pythonapi.PyCapsule_GetPointer(capsule, b"plugin")
return data
mylib = _libpymolfile
mylist = mylib.molfile_plugin_list(200)
numlist = mylib.molfile_init()
print(numlist)
for i in range(numlist):
testplugin = mylib.molfile_plugin_info(mylist, i)
print(i, testplugin)
plugin = mylib.get_plugin(mylist, 81)
print(plugin)
natoms=0
numatoms=molnatoms(natoms)
fname="../../test/md.gro"
ftype="gro"
pluginhandle = mylib.open_file_read(plugin, fname, ftype, natoms)
print("This passed")
print(pluginhandle)
print("This passed too")
print(pluginhandle.natoms)
print("Here")
x = numpy.array([
('C1','C','ACE',0,'','','','',1.0,1.0,12.011,6,1.0,6),
('C2','C','ACE',0,'','','','',1.0,1.0,12.011,6,1.0,6)
],
dtype=[
('name', 'S16'), ('type', 'S16'), ('resname', 'S8'),
('resid', 'i4'), ('segid', 'S8'), ('chain', 'S2'),
('altloc', 'S2'), ('insertion', 'S2'), ('occupancy', 'f8'),
('bfactor', 'f8'), ('mass', 'f8'), ('charge', 'f8'),
('radius', 'f8'), ('atomicnumber', 'i4')
]
)
print(x)
print(x.__array_interface__)
print(x.__array_interface__["descr"])
print(x.__array_struct__)
#y = mylib.read_fill_structure(pluginhandle, x)
y = mylib.print_array_struct(x)
print('Test')
print(y)
#outarray = mylib.get_structure(pluginhandle)
#print(outarray)
#print(type(outarray))
#for i in outarray:
# print(i)
Cython -a numind.pyx --cplus
g++ -fPIC -Wall -Wextra -Wunused-function -shared -I/labEnv3/lib/python3.6/site-packages/numpy/core/include/ numind.cpp -o numind.so -I/labEnv3/include/python3.6m/ -L/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib -lpython3.6
swig -py3 -Wall -c++ -python numpy_swig.i
g++ -fPIC -Wall -Wextra -Wunused-function -shared -I/labEnv3/lib/python3.6/site-packages/numpy/core/include/ -I. numpy_swig_wrap.cxx -o _numpy_swig.so -I/labEnv3/include/python3.6m/ -L/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib -lpython3.6
swig -py3 -Wall -c++ -python libpymolfile.i
g++ -fPIC -Wall -Wextra -Wunused-function -shared -I/labEnv3/lib/python3.6/site-packages/numpy/core/include/ -I. libpymolfile_wrap.cxx pymolfile.c -o _libpymolfile.so -Ivmd_molfile_plugins/include/ -Ilib/ -L. lib/libmolfile_plugin.a -I/labEnv3/include/python3.6m/ -L/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib -lpython3.6
g++ -fPIC -Wall -Wextra -Wunused-function -shared -g -I/labEnv3/lib/python3.6/site-packages/numpy/core/include/ -I. libpymolfile_wrap.cxx pymolfile.c -o _libpymolfile.so -Ivmd_molfile_plugins/include/ -Ilib/ -L. lib/libmolfile_plugin.a -I/labEnv3/include/python3.6m/ -L/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib -lpython3.6
This diff is collapsed.
This diff is collapsed.
......@@ -324,6 +324,15 @@ int structure_read(molfile_plugin_t* plugin, void* fhandle, int *options,
%rename (read_structure) my_read_structure;
extern PyObject * my_read_structure(PyObject* molpack);
%feature("autodoc", "0") get_structure;
extern PyObject * get_structure(PyObject* molpack);
%feature("autodoc", "0") read_fill_structure;
extern PyObject * read_fill_structure(PyObject* molpack, PyObject* prototype);
%feature("autodoc", "0") print_array_struct;
extern PyObject* print_array_struct(PyObject* prototype);
/*
%feature("autodoc", "0") my_read_structure;
%rename (read_structure) my_read_structure;
......
......@@ -113,92 +113,6 @@ pluginNOMEM = _libpymolfile.pluginNOMEM
pluginENDOFFILE = _libpymolfile.pluginENDOFFILE
pluginFILENOTFOUND = _libpymolfile.pluginFILENOTFOUND
pluginFORMATERROR = _libpymolfile.pluginFORMATERROR
class MolAtoms(_object):
__swig_setmethods__ = {}
__setattr__ = lambda self, name, value: _swig_setattr(self, MolAtoms, name, value)
__swig_getmethods__ = {}
__getattr__ = lambda self, name: _swig_getattr(self, MolAtoms, name)
__repr__ = _swig_repr
__swig_setmethods__["name"] = _libpymolfile.MolAtoms_name_set
__swig_getmethods__["name"] = _libpymolfile.MolAtoms_name_get
if _newclass:
name = _swig_property(_libpymolfile.MolAtoms_name_get, _libpymolfile.MolAtoms_name_set)
__swig_setmethods__["type"] = _libpymolfile.MolAtoms_type_set
__swig_getmethods__["type"] = _libpymolfile.MolAtoms_type_get
if _newclass:
type = _swig_property(_libpymolfile.MolAtoms_type_get, _libpymolfile.MolAtoms_type_set)
__swig_setmethods__["resname"] = _libpymolfile.MolAtoms_resname_set
__swig_getmethods__["resname"] = _libpymolfile.MolAtoms_resname_get
if _newclass:
resname = _swig_property(_libpymolfile.MolAtoms_resname_get, _libpymolfile.MolAtoms_resname_set)
__swig_setmethods__["resid"] = _libpymolfile.MolAtoms_resid_set
__swig_getmethods__["resid"] = _libpymolfile.MolAtoms_resid_get
if _newclass:
resid = _swig_property(_libpymolfile.MolAtoms_resid_get, _libpymolfile.MolAtoms_resid_set)
__swig_setmethods__["segid"] = _libpymolfile.MolAtoms_segid_set
__swig_getmethods__["segid"] = _libpymolfile.MolAtoms_segid_get
if _newclass:
segid = _swig_property(_libpymolfile.MolAtoms_segid_get, _libpymolfile.MolAtoms_segid_set)
__swig_setmethods__["chain"] = _libpymolfile.MolAtoms_chain_set
__swig_getmethods__["chain"] = _libpymolfile.MolAtoms_chain_get
if _newclass:
chain = _swig_property(_libpymolfile.MolAtoms_chain_get, _libpymolfile.MolAtoms_chain_set)
__swig_setmethods__["altloc"] = _libpymolfile.MolAtoms_altloc_set
__swig_getmethods__["altloc"] = _libpymolfile.MolAtoms_altloc_get
if _newclass:
altloc = _swig_property(_libpymolfile.MolAtoms_altloc_get, _libpymolfile.MolAtoms_altloc_set)
__swig_setmethods__["insertion"] = _libpymolfile.MolAtoms_insertion_set
__swig_getmethods__["insertion"] = _libpymolfile.MolAtoms_insertion_get
if _newclass:
insertion = _swig_property(_libpymolfile.MolAtoms_insertion_get, _libpymolfile.MolAtoms_insertion_set)
__swig_setmethods__["occupancy"] = _libpymolfile.MolAtoms_occupancy_set
__swig_getmethods__["occupancy"] = _libpymolfile.MolAtoms_occupancy_get
if _newclass:
occupancy = _swig_property(_libpymolfile.MolAtoms_occupancy_get, _libpymolfile.MolAtoms_occupancy_set)
__swig_setmethods__["bfactor"] = _libpymolfile.MolAtoms_bfactor_set
__swig_getmethods__["bfactor"] = _libpymolfile.MolAtoms_bfactor_get
if _newclass:
bfactor = _swig_property(_libpymolfile.MolAtoms_bfactor_get, _libpymolfile.MolAtoms_bfactor_set)
__swig_setmethods__["mass"] = _libpymolfile.MolAtoms_mass_set
__swig_getmethods__["mass"] = _libpymolfile.MolAtoms_mass_get
if _newclass:
mass = _swig_property(_libpymolfile.MolAtoms_mass_get, _libpymolfile.MolAtoms_mass_set)
__swig_setmethods__["charge"] = _libpymolfile.MolAtoms_charge_set
__swig_getmethods__["charge"] = _libpymolfile.MolAtoms_charge_get
if _newclass:
charge = _swig_property(_libpymolfile.MolAtoms_charge_get, _libpymolfile.MolAtoms_charge_set)
__swig_setmethods__["radius"] = _libpymolfile.MolAtoms_radius_set
__swig_getmethods__["radius"] = _libpymolfile.MolAtoms_radius_get
if _newclass:
radius = _swig_property(_libpymolfile.MolAtoms_radius_get, _libpymolfile.MolAtoms_radius_set)
__swig_setmethods__["atomicnumber"] = _libpymolfile.MolAtoms_atomicnumber_set
__swig_getmethods__["atomicnumber"] = _libpymolfile.MolAtoms_atomicnumber_get
if _newclass:
atomicnumber = _swig_property(_libpymolfile.MolAtoms_atomicnumber_get, _libpymolfile.MolAtoms_atomicnumber_set)
__swig_setmethods__["ctnumber"] = _libpymolfile.MolAtoms_ctnumber_set
__swig_getmethods__["ctnumber"] = _libpymolfile.MolAtoms_ctnumber_get
if _newclass:
ctnumber = _swig_property(_libpymolfile.MolAtoms_ctnumber_get, _libpymolfile.MolAtoms_ctnumber_set)
def __init__(self):
this = _libpymolfile.new_MolAtoms()
try:
self.this.append(this)
except __builtin__.Exception:
self.this = this
__swig_destroy__ = _libpymolfile.delete_MolAtoms
__del__ = lambda self: None
MolAtoms_swigregister = _libpymolfile.MolAtoms_swigregister
MolAtoms_swigregister(MolAtoms)
def del_plugin_structure(pymolfile_atoms: 'PyObject *') -> "void":
return _libpymolfile.del_plugin_structure(pymolfile_atoms)
del_plugin_structure = _libpymolfile.del_plugin_structure
def alloc_plugin_structure(arg1: 'PyObject *', args: 'PyObject *') -> "PyObject *":
return _libpymolfile.alloc_plugin_structure(arg1, args)
alloc_plugin_structure = _libpymolfile.alloc_plugin_structure
def del_plugin(pymolfile_plugin: 'PyObject *') -> "void":
return _libpymolfile.del_plugin(pymolfile_plugin)
......@@ -243,6 +157,18 @@ def open_file_read(plugin: 'molfile_plugin_t *', fname: 'char *', ftype: 'char *
def read_structure(molpack: 'PyObject *') -> "PyObject *":
"""read_structure(molpack) -> PyObject *"""
return _libpymolfile.read_structure(molpack)
def get_structure(molpack: 'PyObject *') -> "PyObject *":
"""get_structure(molpack) -> PyObject *"""
return _libpymolfile.get_structure(molpack)
def read_fill_structure(molpack: 'PyObject *', prototype: 'PyObject *') -> "PyObject *":
"""read_fill_structure(molpack, prototype) -> PyObject *"""
return _libpymolfile.read_fill_structure(molpack, prototype)
def print_array_struct(prototype: 'PyObject *') -> "PyObject *":
"""print_array_struct(prototype) -> PyObject *"""
return _libpymolfile.print_array_struct(prototype)
# This file is compatible with both classic and new-style classes.
This diff is collapsed.
Cython -a numind.pyx --cplus
g++ -fPIC -Wall -Wextra -Wunused-function -shared -I/labEnv3/lib/python3.6/site-packages/numpy/core/include/ numind.cpp -o numind.so -I/labEnv3/include/python3.6m/ -L/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib -lpython3.6
This diff is collapsed.
#ifndef NUMIND_H
#define NUMIND_H
typedef struct SignedIntBuf
{
int* data;
int shape[2];
int strides[2];
} SignedIntBuf;
#endif
This diff is collapsed.
# This Pyrex extension class can take a numpy/numarray/Numeric object
# as a parameter and wrap it so that its information can be accessed
# in a standard way, both in Python space and C space.
#
# Heavily based on an idea of Andrew Straw. See
# http://www.scipy.org/Cookbook/ArrayStruct_and_Pyrex
# Very inspiring! :-)
#
# First version: 2006-03-25
# Last update: 2006-03-25
# Author: Francesc Altet
import sys
from cpython.pycapsule cimport *
cdef extern from "Python.h":
ctypedef int Py_intptr_t
ctypedef object PyObject
long PyInt_AsLong(object)
void Py_INCREF(object)
void Py_DECREF(object)
cdef extern from "stdlib.h":
ctypedef long size_t
ctypedef long intptr_t
void *malloc(size_t size)
void free(void* ptr)
cdef extern from "numind.h":
ctypedef struct SignedIntBuf
# for PyArrayInterface:
CONTIGUOUS=0x01
FORTRAN=0x02
ALIGNED=0x100
NOTSWAPPED=0x200
WRITEABLE=0x400
# byteorder dictionary
byteorder = {'<':'little', '>':'big'}
ctypedef struct PyArrayInterface:
int version # contains the integer 2 as a sanity check
int nd # number of dimensions
char typekind # kind in array --- character code of typestr
int itemsize # size of each element
int flags # flags indicating how the data should be interpreted
Py_intptr_t *shape # A length-nd array of shape information
Py_intptr_t *strides # A length-nd array of stride information
void *data # A pointer to the first element of the array
cdef void* free_array_interface(object arr):
Py_DECREF(arr)
cdef class NumInd:
cdef void *data
cdef int _nd
cdef Py_intptr_t *_shape
cdef Py_intptr_t *_strides
cdef PyArrayInterface *inter
cdef object _t_shape, _t_strides, _undarray
def __init__(self, object undarray):
cdef int i, stride
cdef object array_shape, array_strides
# Keep a reference to the underlying object
self._undarray = undarray
# Get the shape and strides C arrays
array_shape = undarray.__array_interface__["shape"]
self._t_shape = array_shape
# The number of dimensions
self._nd = len(array_shape)
# The shape
self._shape = <Py_intptr_t *>malloc(self._nd*sizeof(Py_intptr_t))
for i from 0 <= i < self._nd:
self._shape[i] = self._t_shape[i]
# The strides (compute them if needed)
array_strides = undarray.__array_interface__["strides"]
self._t_strides = array_strides
self._strides = <Py_intptr_t *>malloc(self._nd*sizeof(Py_intptr_t))
if array_strides:
for i from 0 <= i < self._nd:
self._strides[i] = array_strides[i]
else:
# strides is None. Compute them explicitely.
self._t_strides = [0] * self._nd
stride = int(self.typestr[2:])
for i from self._nd > i >= 0:
self._strides[i] = stride
self._t_strides[i] = stride
stride = stride * array_shape[i]
self._t_strides = tuple(self._t_strides)
# Populate the C array interface
self.inter = self._get_array_interface()
# Properties. This are visible from Python space.
# Add as many as you want.
property undarray: # Returns the underlying array
def __get__(self):
return self._undarray
property shape:
def __get__(self):
return self._t_shape
property strides:
def __get__(self):
return self._t_strides
property typestr:
def __get__(self):
return self._undarray.__array_interface__["typestr"]
property typekind:
def __get__(self):
return chr(self.inter.typekind)
property readonly:
def __get__(self):
return self._undarray.__array_interface__["data"][1]
property __array_struct__:
"Allows other numerical packages to obtain a new object."
def __get__(self):
if hasattr(self._undarray, "__array_struct__"):
return self._undarray.__array_struct__
else:
# No an underlying array with __array_struct__
# Deliver an equivalent PyCObject.
Py_INCREF(self)
return PyCapsule_New(<void*>self.inter,
"struct array",
<PyCapsule_Destructor>free_array_interface)
cdef PyArrayInterface *_get_array_interface(self):
"Populates the array interface"
cdef PyArrayInterface *inter
cdef object undarray, data_address, typestr
cdef object obj
undarray = self._undarray
typestr = self.typestr
inter = <PyArrayInterface *>malloc(sizeof(PyArrayInterface))
if inter is NULL:
raise MemoryError()
inter.version = 2
inter.nd = self._nd
inter.typekind = ord(typestr[1])
inter.itemsize = int(typestr[2:])
inter.flags = 0 # initialize flags
if typestr[0] == '|':
inter.flags = inter.flags | NOTSWAPPED
elif byteorder[typestr[0]] == sys.byteorder:
inter.flags = inter.flags | NOTSWAPPED
if not self.readonly:
inter.flags = inter.flags | WRITEABLE
# XXX how to determine the ALIGNED flag?
inter.strides = self._strides
inter.shape = self._shape
# Get the data address
obj = undarray.__array_interface__["data"]
data_address = obj[0]
inter.data = <void*>PyInt_AsLong(data_address)
return inter
# This is just an example on how to modify the data in C space
# (and at C speed! :-)
def modify(self):
"Modify the values of the underlying array"
cdef long *ldata
cdef double *fdata
cdef int i
# Modify just the first row
if chr(self.inter.typekind) == 'i':
ldata = <long *>self.inter.data
for i from 0 <= i < self.inter.shape[self.inter.nd-1]:
ldata[i] = ldata[i] + 1
elif chr(self.inter.typekind) == 'f':
fdata = <double *>self.inter.data
for i from 0 <= i < self.inter.shape[self.inter.nd-1]:
fdata[i] = fdata[i] + 1
def __dealloc__(self):
free(self._shape)
free(self._strides)
free(self.inter)
import numpy
import ctypes
import numind
# Create an arbitrary object for each package
np=numpy.arange(12, dtype=numpy.float)
#np=numpy.arange(12)
np.shape = (4,3)
#ns = _numpy_swig(2,2)
#print(ns)
# Wrap the different objects with the NumInd class
# and execute some actions on it
##for obj in [np]:
# ni = _numpy_swig
# print("original object type-->", type(ni.inter))
# # Print some values
# #print("typestr --> {0}", ni.typestr)
# #print("shape --> {0}", ni.shape)
# #print("strides --> {0}", ni.strides)
# npa = numpy.asarray(ni)
# print("object after a numpy re-wrapping --> " , npa)
# #ni.modify()
# #print("object after modification in C space --> {0}", npa)
# Wrap the different objects with the NumInd class
# and execute some actions on it
for obj in [np]:
ni = numind.NumInd(obj)
print("original object type-->", type(ni.undarray))
# Print some values
print("typestr -->", ni.typestr)
print("typekind -->", ni.typekind)
print("shape -->", ni.shape)
print("strides -->", ni.strides)
npa = numpy.asarray(ni)
print("object after a numpy re-wrapping -->", npa)
ni.modify()
print("object after modification in C space -->", npa)
#ifndef NUMPY_SWIG
#define NUMPY_SWIG
typedef struct SignedIntBuf
{
int* data;
int shape[2];
int strides[2];
} SignedIntBuf;
#endif
Markdown is supported
0% or .