added libsvm wrapper

This commit is contained in:
Araq
2012-04-04 16:01:28 +02:00
parent b9f99565e9
commit a4a99ae997
7 changed files with 253 additions and 0 deletions

View File

@@ -584,3 +584,9 @@ Data Compression and Archiving
Interface to the `lib zip <http://www.nih.at/libzip/index.html>`_ library by
Dieter Baron and Thomas Klausner.
Scientific computing
--------------------
* `libsvm <libsvm.html>`_
Low level wrapper for `libsvm <http://www.csie.ntu.edu.tw/~cjlin/libsvm/>`_.

46
lib/pure/endians.nim Normal file
View File

@@ -0,0 +1,46 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2012 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## This module contains helpers that deal with `endian`:idx: changes.
proc swapEndian64*(outp, inp: pointer) =
## copies `inp` to `outp` swapping bytes. Both buffers are supposed to
## contain at least 8 bytes.
var i = cast[cstring](inp)
var o = cast[cstring](outp)
o[0] = i[7]
o[1] = i[6]
o[2] = i[5]
o[3] = i[4]
o[4] = i[3]
o[5] = i[2]
o[6] = i[1]
o[7] = i[0]
proc swapEndian32*(outp, inp: pointer) =
## copies `inp` to `outp` swapping bytes. Both buffers are supposed to
## contain at least 4 bytes.
var i = cast[cstring](inp)
var o = cast[cstring](outp)
o[0] = i[3]
o[1] = i[2]
o[2] = i[1]
o[3] = i[0]
when system.cpuEndian == bigEndian:
proc littleEndian64*(outp, inp: pointer) {.inline.} = swapEndian64(outp, inp)
proc littleEndian32*(outp, inp: pointer) {.inline.} = swapEndian32(outp, inp)
proc bigEndian64*(outp, inp: pointer) {.inline.} = copyMem(outp, inp, 8)
proc bigEndian32*(outp, inp: pointer) {.inline.} = copyMem(outp, inp, 4)
else:
proc littleEndian64*(outp, inp: pointer) {.inline.} = copyMem(outp, inp, 8)
proc littleEndian32*(outp, inp: pointer) {.inline.} = copyMem(outp, inp, 4)
proc bigEndian64*(outp, inp: pointer) {.inline.} = swapEndian64(outp, inp)
proc bigEndian32*(outp, inp: pointer) {.inline.} = swapEndian32(outp, inp)

81
lib/pure/oids.nim Normal file
View File

@@ -0,0 +1,81 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2012 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## Nimrod OID support. An OID consists of a timestamp, a unique counter
## and a random value. This combination should suffice to produce a globally
## distributed unique ID. This implementation was extracted from the
## Mongodb interface. This calls ``math.randomize()`` for the first call of
## ``genOid``.
import times, endians
type
Toid* {.pure, final.} = object ## an OID
time: int32 ##
fuzz: int32 ##
count: int32 ##
proc hexbyte*(hex: char): int =
case hex
of '0'..'9': result = (ord(hex) - ord('0'))
of 'a'..'f': result = (ord(hex) - ord('a') + 10)
of 'A'..'F': result = (ord(hex) - ord('A') + 10)
else: nil
proc parseOid*(str: cstring): TOid =
## parses an OID.
var bytes = cast[cstring](addr(result.time))
var i = 0
while i < 12:
bytes[i] = chr((hexbyte(str[2 * i]) shl 4) or hexbyte(str[2 * i + 1]))
inc(i)
proc oidToString*(oid: TOid, str: cstring) =
const hex = "0123456789abcdef"
# work around a compiler bug:
var str = str
var o = oid
var bytes = cast[cstring](addr(o))
var i = 0
while i < 12:
let b = bytes[i].ord
str[2 * i] = hex[(b and 0xF0) shr 4]
str[2 * i + 1] = hex[b and 0xF]
inc(i)
str[24] = '\0'
var
incr, fuzz: int
proc genOid*(): TOid =
## generates a new OID.
proc rand(): cint {.importc: "rand", nodecl.}
proc gettime(dummy: ptr cint): cint {.importc: "time", header: "<time.h>".}
proc srand(seed: cint) {.importc: "srand", nodecl.}
var t = gettime(nil)
var i = int32(incr)
atomicInc(incr)
if fuzz == 0:
# racy, but fine semantically:
srand(t)
fuzz = rand()
bigEndian32(addr result.time, addr(t))
result.fuzz = fuzz
bigEndian32(addr result.count, addr(i))
proc generatedTime*(oid: TOid): TTime =
## returns the generated timestamp of the OID.
var tmp: int32
var dummy = oid.time
bigEndian32(addr(tmp), addr(dummy))
result = TTime(tmp)

116
lib/wrappers/libsvm.nim Normal file
View File

@@ -0,0 +1,116 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2012 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## This module is a low level wrapper for `libsvm`:idx:.
{.deadCodeElim: on.}
const
LIBSVM_VERSION* = 312
when defined(windows):
const svmdll* = "libsvm.dll"
elif defined(macosx):
const svmdll* = "libsvm.dylib"
else:
const svmdll* = "libsvm.so"
type
Tnode*{.pure, final.} = object
index*: cint
value*: cdouble
Tproblem*{.pure, final.} = object
L*: cint
y*: ptr cdouble
x*: ptr ptr Tnode
Ttype*{.size: sizeof(cint).} = enum
C_SVC, NU_SVC, ONE_CLASS, EPSILON_SVR, NU_SVR
TKernelType*{.size: sizeof(cint).} = enum
LINEAR, POLY, RBF, SIGMOID, PRECOMPUTED
Tparameter*{.pure, final.} = object
typ*: TType
kernelType*: TKernelType
degree*: cint # for poly
gamma*: cdouble # for poly/rbf/sigmoid
coef0*: cdouble # for poly/sigmoid
# these are for training only
cache_size*: cdouble # in MB
eps*: cdouble # stopping criteria
C*: cdouble # for C_SVC, EPSILON_SVR and NU_SVR
nr_weight*: cint # for C_SVC
weight_label*: ptr cint # for C_SVC
weight*: ptr cdouble # for C_SVC
nu*: cdouble # for NU_SVC, ONE_CLASS, and NU_SVR
p*: cdouble # for EPSILON_SVR
shrinking*: cint # use the shrinking heuristics
probability*: cint # do probability estimates
#
# svm_model
#
type
TModel*{.pure, final.} = object
param*: Tparameter # parameter
nr_class*: cint # number of classes, = 2 in regression/one class svm
L*: cint # total #SV
SV*: ptr ptr Tnode # SVs (SV[l])
sv_coef*: ptr ptr cdouble # coefficients for SVs in decision functions (sv_coef[k-1][l])
rho*: ptr cdouble # constants in decision functions (rho[k*(k-1)/2])
probA*: ptr cdouble # pariwise probability information
probB*: ptr cdouble # for classification only
label*: ptr cint # label of each class (label[k])
nSV*: ptr cint # number of SVs for each class (nSV[k])
# nSV[0] + nSV[1] + ... + nSV[k-1] = l
# XXX
free_sv*: cint # 1 if svm_model is created by svm_load_model
# 0 if svm_model is created by svm_train
proc train*(prob: ptr Tproblem, param: ptr Tparameter): ptr Tmodel{.cdecl,
importc: "svm_train", dynlib: svmdll.}
proc cross_validation*(prob: ptr Tproblem, param: ptr Tparameter, nr_fold: cint,
target: ptr cdouble){.cdecl,
importc: "svm_cross_validation", dynlib: svmdll.}
proc save_model*(model_file_name: cstring, model: ptr Tmodel): cint{.cdecl,
importc: "svm_save_model", dynlib: svmdll.}
proc load_model*(model_file_name: cstring): ptr Tmodel{.cdecl,
importc: "svm_load_model", dynlib: svmdll.}
proc get_svm_type*(model: ptr Tmodel): cint{.cdecl, importc: "svm_get_svm_type",
dynlib: svmdll.}
proc get_nr_class*(model: ptr Tmodel): cint{.cdecl, importc: "svm_get_nr_class",
dynlib: svmdll.}
proc get_labels*(model: ptr Tmodel, label: ptr cint){.cdecl,
importc: "svm_get_labels", dynlib: svmdll.}
proc get_svr_probability*(model: ptr Tmodel): cdouble{.cdecl,
importc: "svm_get_svr_probability", dynlib: svmdll.}
proc predict_values*(model: ptr Tmodel, x: ptr Tnode, dec_values: ptr cdouble): cdouble{.
cdecl, importc: "svm_predict_values", dynlib: svmdll.}
proc predict*(model: ptr Tmodel, x: ptr Tnode): cdouble{.cdecl,
importc: "svm_predict", dynlib: svmdll.}
proc predict_probability*(model: ptr Tmodel, x: ptr Tnode,
prob_estimates: ptr cdouble): cdouble{.cdecl,
importc: "svm_predict_probability", dynlib: svmdll.}
proc free_model_content*(model_ptr: ptr Tmodel){.cdecl,
importc: "svm_free_model_content", dynlib: svmdll.}
proc free_and_destroy_model*(model_ptr_ptr: ptr ptr Tmodel){.cdecl,
importc: "svm_free_and_destroy_model", dynlib: svmdll.}
proc destroy_param*(param: ptr Tparameter){.cdecl, importc: "svm_destroy_param",
dynlib: svmdll.}
proc check_parameter*(prob: ptr Tproblem, param: ptr Tparameter): cstring{.
cdecl, importc: "svm_check_parameter", dynlib: svmdll.}
proc check_probability_model*(model: ptr Tmodel): cint{.cdecl,
importc: "svm_check_probability_model", dynlib: svmdll.}
proc set_print_string_function*(print_func: proc (arg: cstring) {.cdecl.}){.
cdecl, importc: "svm_set_print_string_function", dynlib: svmdll.}

View File

@@ -371,6 +371,8 @@
# to keep it up to date
#==============================================================================
{.deadCodeElim: on.}
when defined(LINUX):
import
X, XLib, XUtil

View File

@@ -29,6 +29,7 @@ Library Additions
- The stdlib can now be avoided to a point where C code generation for 16bit
micro controllers is feasible.
- Added a new OpenGL wrapper that supports OpenGL up to version 4.2.
- Added a wrapper for ``libsvm``.
Changes affecting backwards compatibility

View File

@@ -55,6 +55,7 @@ webdoc: "posix/posix;wrappers/odbcsql;impure/dialogs"
webdoc: "wrappers/zip/zlib;wrappers/zip/libzip"
webdoc: "wrappers/cairo"
webdoc: "wrappers/gtk"
webdoc: "wrappers/libsvm.nim"
webdoc: "windows"
webdoc: "wrappers/x11;wrappers/opengl;wrappers/sdl;wrappers/lua"
webdoc: "wrappers/readline/readline;wrappers/readline/history"