Commits

Miha Stajdohar committed 286e138

  • Participants
  • Parent commits cd2cbec

Comments (0)

Files changed (316)

File source/BUILDING

+To compile Orange, you need Python 2.2 or later. You don't
+need Python sources, except for the header and library files
+that come with the basic distribution anyway.
+
+This file does not cover building the C4.5 plugin.
+See doc/reference/C45Learner.htm for instructions.
+
+You don't need C4.5 sources to build Orange on Linux and
+Mac OS X (as was the case with previous versions of Orange).
+
+Please report any problems to janez.demsar@fri.uni-lj.si.
+
+
+Compiling instructions for MSVC 6.0
+-----------------------------------
+
+Although the provided project files are for MS VC 6.0, Orange
+can (in principle; we are not regularly checking it) also be
+compiled by MS VC .Net - just let it import and convert the files.
+
+1.  Set the environment variable PYTHON to Python's root (e.g.
+    c:\python23). This is used for finding include files and libraries.
+
+2.  The workspace file is in subdirectory source. Open it and
+    compile. Note that if you want to compile a debug version of
+    Orange, you'll need to have the debug version of Python as
+    well (python23_d.lib, python23_d.dll etc). See file
+    debugging_orange.txt if you need a hint on that.
+
+3.  Make sure that Python will find the compiled modules. You can set
+    the PYTHONPATH, create an appropriate orange.pth file in Python's
+    directory site-packages, create a corresponding registry key or
+    simply copy the files to Python's lib directory.
+
+
+Compiling instructions for Linux
+--------------------------------
+
+To compile orange, you'll need a newer gcc (version 3.2 works;
+we are not sure about older compilers).
+
+1.  Run make (Makefile is in subdirectory source).
+
+    If gcc complains that it cannot find Python.h, find it
+    yourself and manually correct the PYTHONDIR in Makefile.
+    
+    Warnings are disabled to avoid thousands of warnings
+    about invalid offsetof from non-POD type. (These didn't
+    occur in earlier versions of gcc; we might try to do something
+    about it.) If you like warnings, edit the Makefile to
+    enable them.
+
+2.  To let Python know where to find Orange, you should either
+    add the path to PYTHONPATH or create a file orange.pth in
+    Python's directory site-packages. Running 'make install'
+    will tell you the paths you need.
+    
+
+Compiling instructions for Mac OS X
+-----------------------------------
+
+Mac OS X comes without gcc but you get it with Xcode. You can
+install Xcode from your Mac OS X installation disk or from:
+
+  http://developer.apple.com/technology/xcode.html
+
+After having it installed and Orange source code downloaded:
+
+1. Uncompress the archive.
+2. Go to the uncompressed directory and run 'make' after which
+   you will get compiled modules in a parent directory.
+3. You can move those modules where Python will find them
+   (for example where PYTHONPATH is pointing to).
+4. Make sure with 'otool -L' that paths to dynamic libraries
+   modules are using are correct. If not, use 'install_name_tool'
+   to correct them.

File source/Makefile

+# Set ORANGE_LIBDIR to some other directory if ../.. is on
+# a vfat file-system (not common, but I need it)
+# (This is needed because vfat doesn't support symbolic links)
+ifndef ORANGE_LIBDIR
+  ORANGE_LIBDIR=../..
+endif
+
+MODULES=include orange orangeom orangene corn statc
+ACTIONS=all clean cleantemp
+
+$(ACTIONS):
+	(for MODULE in $(MODULES) ; \
+	   do if ! $(MAKE) $@ -C $$MODULE OLD=$(ORANGE_LIBDIR); then exit 1; fi; done)
+
+install: # all orange.pth canvas bininstall docinstall
+	@echo "Please use Python Distutils to install Orange."
+

File source/Orange.dsw

+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "Corn"=.\corn\Corn.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name include
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "Orange"=.\orange\Orange.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name include
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "Statc"=.\statc\Statc.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name include
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "include"=.\include\include.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "orangene"=.\orangene\orangene.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "orangeom"=.\orangeom\orangeom.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+

File source/Orange.sln

+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Corn", "corn\Corn.vcproj", "{DB7466D1-CF93-44A1-9AB2-27290A2EC7C7}"
+	ProjectSection(ProjectDependencies) = postProject
+		{93B854DA-EC3F-4314-B801-58411F9713FD} = {93B854DA-EC3F-4314-B801-58411F9713FD}
+		{745880F1-8F10-4247-B481-E4321BC1BD9F} = {745880F1-8F10-4247-B481-E4321BC1BD9F}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Orange", "orange\Orange.vcproj", "{93B854DA-EC3F-4314-B801-58411F9713FD}"
+	ProjectSection(ProjectDependencies) = postProject
+		{745880F1-8F10-4247-B481-E4321BC1BD9F} = {745880F1-8F10-4247-B481-E4321BC1BD9F}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Statc", "statc\Statc.vcproj", "{A0E81B4F-E592-4002-A6BE-5EAA1DD86A25}"
+	ProjectSection(ProjectDependencies) = postProject
+		{745880F1-8F10-4247-B481-E4321BC1BD9F} = {745880F1-8F10-4247-B481-E4321BC1BD9F}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "include", "include\include.vcproj", "{745880F1-8F10-4247-B481-E4321BC1BD9F}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "orangene", "orangene\orangene.vcproj", "{A9DFB98F-8235-4D5B-BFE2-BBCB9A283D98}"
+	ProjectSection(ProjectDependencies) = postProject
+		{745880F1-8F10-4247-B481-E4321BC1BD9F} = {745880F1-8F10-4247-B481-E4321BC1BD9F}
+		{93B854DA-EC3F-4314-B801-58411F9713FD} = {93B854DA-EC3F-4314-B801-58411F9713FD}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "orangeom", "orangeom\orangeom.vcproj", "{1DD56474-1110-413B-80B8-707E8EE28EC6}"
+	ProjectSection(ProjectDependencies) = postProject
+		{93B854DA-EC3F-4314-B801-58411F9713FD} = {93B854DA-EC3F-4314-B801-58411F9713FD}
+		{745880F1-8F10-4247-B481-E4321BC1BD9F} = {745880F1-8F10-4247-B481-E4321BC1BD9F}
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		Release|Win32 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{DB7466D1-CF93-44A1-9AB2-27290A2EC7C7}.Debug|Win32.ActiveCfg = Debug|Win32
+		{DB7466D1-CF93-44A1-9AB2-27290A2EC7C7}.Debug|Win32.Build.0 = Debug|Win32
+		{DB7466D1-CF93-44A1-9AB2-27290A2EC7C7}.Release|Win32.ActiveCfg = Release|Win32
+		{DB7466D1-CF93-44A1-9AB2-27290A2EC7C7}.Release|Win32.Build.0 = Release|Win32
+		{93B854DA-EC3F-4314-B801-58411F9713FD}.Debug|Win32.ActiveCfg = Debug|Win32
+		{93B854DA-EC3F-4314-B801-58411F9713FD}.Debug|Win32.Build.0 = Debug|Win32
+		{93B854DA-EC3F-4314-B801-58411F9713FD}.Release|Win32.ActiveCfg = Release|Win32
+		{93B854DA-EC3F-4314-B801-58411F9713FD}.Release|Win32.Build.0 = Release|Win32
+		{A0E81B4F-E592-4002-A6BE-5EAA1DD86A25}.Debug|Win32.ActiveCfg = Debug|Win32
+		{A0E81B4F-E592-4002-A6BE-5EAA1DD86A25}.Debug|Win32.Build.0 = Debug|Win32
+		{A0E81B4F-E592-4002-A6BE-5EAA1DD86A25}.Release|Win32.ActiveCfg = Release|Win32
+		{A0E81B4F-E592-4002-A6BE-5EAA1DD86A25}.Release|Win32.Build.0 = Release|Win32
+		{745880F1-8F10-4247-B481-E4321BC1BD9F}.Debug|Win32.ActiveCfg = Debug|Win32
+		{745880F1-8F10-4247-B481-E4321BC1BD9F}.Debug|Win32.Build.0 = Debug|Win32
+		{745880F1-8F10-4247-B481-E4321BC1BD9F}.Release|Win32.ActiveCfg = Release|Win32
+		{745880F1-8F10-4247-B481-E4321BC1BD9F}.Release|Win32.Build.0 = Release|Win32
+		{A9DFB98F-8235-4D5B-BFE2-BBCB9A283D98}.Debug|Win32.ActiveCfg = Debug|Win32
+		{A9DFB98F-8235-4D5B-BFE2-BBCB9A283D98}.Debug|Win32.Build.0 = Debug|Win32
+		{A9DFB98F-8235-4D5B-BFE2-BBCB9A283D98}.Release|Win32.ActiveCfg = Release|Win32
+		{A9DFB98F-8235-4D5B-BFE2-BBCB9A283D98}.Release|Win32.Build.0 = Release|Win32
+		{1DD56474-1110-413B-80B8-707E8EE28EC6}.Debug|Win32.ActiveCfg = Debug|Win32
+		{1DD56474-1110-413B-80B8-707E8EE28EC6}.Debug|Win32.Build.0 = Debug|Win32
+		{1DD56474-1110-413B-80B8-707E8EE28EC6}.Release|Win32.ActiveCfg = Release|Win32
+		{1DD56474-1110-413B-80B8-707E8EE28EC6}.Release|Win32.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal

File source/_pyxtract.bat

+@echo off
+cd orange
+python ..\pyxtract\defvectors.py
+
+rem I know this is stupid, but works under any shell
+cd ..\orange
+call _pyxtract.bat
+cd ..\orangene
+call _pyxtract.bat
+cd ..\orangeom
+call _pyxtract.bat
+cd ..

File source/_underscored_manual

+Example
+getweight get_weight
+setweight set_weight
+removeweight remove_weight
+getmeta get_meta
+getmetas get_metas
+hasmetas has_meta
+setvalue set_value
+setmeta set_meta
+removemeta remove_meta
+getclass get_class
+setclass set_class
+
+Value
+firstvalue first_value
+nextvalue next_value
+randomvalue random_value
+
+
+Filter_Python
+*deepCopy deep_copy
+
+MeasureAttribute_Python
+*thresholdFunction threshold_function
+
+Example
+*filterMetas filter_metas
+
+Example.native
+*substituteDC substitute_DC
+*substituteDK substitute_DK
+*substituteOther substitute_other
+

File source/corn/Corn.dsp

+# Microsoft Developer Studio Project File - Name="Corn" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=Corn - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "Corn.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "Corn.mak" CFG="Corn - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "Corn - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "Corn - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "Corn - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "obj/Release"
+# PROP Intermediate_Dir "obj/Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CORN_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GR /GX /O2 /I "../include" /I "$(PYTHON)\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CORN_EXPORTS" /YX /FD /c
+# SUBTRACT CPP /Fr
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 orange.lib /nologo /dll /pdb:none /machine:I386 /out:"obj/Release/corn.pyd" /libpath:"../../lib" /libpath:"$(PYTHON)\libs"
+# SUBTRACT LINK32 /nodefaultlib
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Cmds=..\upx.bat corn
+# End Special Build Tool
+
+!ELSEIF  "$(CFG)" == "Corn - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Corn___Win32_Debug"
+# PROP BASE Intermediate_Dir "Corn___Win32_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "obj/Debug"
+# PROP Intermediate_Dir "obj/Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CORN_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GR /GX /ZI /Od /I "../include" /I "$(PYTHON)\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CORN_EXPORTS" /YX /FD /GZ /c
+# SUBTRACT CPP /Fr
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"../../Corn_d.pyd" /pdbtype:sept /libpath:"$(PYTHON)/libs"
+# SUBTRACT LINK32 /nodefaultlib
+
+!ENDIF 
+
+# Begin Target
+
+# Name "Corn - Win32 Release"
+# Name "Corn - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\corn.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\orange\numeric_interface.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\corn.hpp
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project

File source/corn/Corn.mak

+# Microsoft Developer Studio Generated NMAKE File, Based on Corn.dsp
+!IF "$(CFG)" == ""
+CFG=Corn - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to Corn - Win32 Debug.
+!ENDIF 
+
+!IF "$(CFG)" != "Corn - Win32 Release" && "$(CFG)" != "Corn - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "Corn.mak" CFG="Corn - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "Corn - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "Corn - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE 
+!ERROR An invalid configuration is specified.
+!ENDIF 
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE 
+NULL=nul
+!ENDIF 
+
+!IF  "$(CFG)" == "Corn - Win32 Release"
+
+OUTDIR=.\obj/Release
+INTDIR=.\obj/Release
+# Begin Custom Macros
+OutDir=.\obj/Release
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0" 
+
+ALL : "$(OUTDIR)\corn.pyd"
+
+!ELSE 
+
+ALL : "include - Win32 Release" "$(OUTDIR)\corn.pyd"
+
+!ENDIF 
+
+!IF "$(RECURSE)" == "1" 
+CLEAN :"include - Win32 ReleaseCLEAN" 
+!ELSE 
+CLEAN :
+!ENDIF 
+	-@erase "$(INTDIR)\corn.obj"
+	-@erase "$(INTDIR)\numeric_interface.obj"
+	-@erase "$(INTDIR)\vc60.idb"
+	-@erase "$(OUTDIR)\corn.exp"
+	-@erase "$(OUTDIR)\corn.lib"
+	-@erase "$(OUTDIR)\corn.pyd"
+
+"$(OUTDIR)" :
+    if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /GR /GX /O2 /I "../include" /I "$(PYTHON)\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CORN_EXPORTS" /Fp"$(INTDIR)\Corn.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c 
+
+.c{$(INTDIR)}.obj::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+.cpp{$(INTDIR)}.obj::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+.cxx{$(INTDIR)}.obj::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+.c{$(INTDIR)}.sbr::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+.cpp{$(INTDIR)}.sbr::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+.cxx{$(INTDIR)}.sbr::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\Corn.bsc" 
+BSC32_SBRS= \
+	
+LINK32=link.exe
+LINK32_FLAGS=orange.lib /nologo /dll /pdb:none /machine:I386 /out:"$(OUTDIR)\corn.pyd" /implib:"$(OUTDIR)\corn.lib" /libpath:"../../lib" /libpath:"$(PYTHON)\libs" 
+LINK32_OBJS= \
+	"$(INTDIR)\corn.obj" \
+	"$(INTDIR)\numeric_interface.obj" \
+	"..\include\obj\Release\include.lib"
+
+"$(OUTDIR)\corn.pyd" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+    $(LINK32) @<<
+  $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+SOURCE="$(InputPath)"
+DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep
+
+ALL : $(DS_POSTBUILD_DEP)
+
+# Begin Custom Macros
+OutDir=.\obj/Release
+# End Custom Macros
+
+$(DS_POSTBUILD_DEP) : "include - Win32 Release" "$(OUTDIR)\corn.pyd"
+   ..\upx.bat corn
+	echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)"
+
+!ELSEIF  "$(CFG)" == "Corn - Win32 Debug"
+
+OUTDIR=.\obj/Debug
+INTDIR=.\obj/Debug
+
+!IF "$(RECURSE)" == "0" 
+
+ALL : "..\..\Corn_d.pyd"
+
+!ELSE 
+
+ALL : "include - Win32 Debug" "..\..\Corn_d.pyd"
+
+!ENDIF 
+
+!IF "$(RECURSE)" == "1" 
+CLEAN :"include - Win32 DebugCLEAN" 
+!ELSE 
+CLEAN :
+!ENDIF 
+	-@erase "$(INTDIR)\corn.obj"
+	-@erase "$(INTDIR)\numeric_interface.obj"
+	-@erase "$(INTDIR)\vc60.idb"
+	-@erase "$(INTDIR)\vc60.pdb"
+	-@erase "$(OUTDIR)\Corn_d.exp"
+	-@erase "$(OUTDIR)\Corn_d.lib"
+	-@erase "$(OUTDIR)\Corn_d.pdb"
+	-@erase "..\..\Corn_d.ilk"
+	-@erase "..\..\Corn_d.pyd"
+
+"$(OUTDIR)" :
+    if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Gm /GR /GX /ZI /Od /I "../include" /I "$(PYTHON)\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CORN_EXPORTS" /Fp"$(INTDIR)\Corn.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c 
+
+.c{$(INTDIR)}.obj::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+.cpp{$(INTDIR)}.obj::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+.cxx{$(INTDIR)}.obj::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+.c{$(INTDIR)}.sbr::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+.cpp{$(INTDIR)}.sbr::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+.cxx{$(INTDIR)}.sbr::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\Corn.bsc" 
+BSC32_SBRS= \
+	
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:yes /pdb:"$(OUTDIR)\Corn_d.pdb" /debug /machine:I386 /out:"../../Corn_d.pyd" /implib:"$(OUTDIR)\Corn_d.lib" /pdbtype:sept /libpath:"$(PYTHON)/libs" 
+LINK32_OBJS= \
+	"$(INTDIR)\corn.obj" \
+	"$(INTDIR)\numeric_interface.obj" \
+	"..\include\obj\Debug\include.lib"
+
+"..\..\Corn_d.pyd" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+    $(LINK32) @<<
+  $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF 
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("Corn.dep")
+!INCLUDE "Corn.dep"
+!ELSE 
+!MESSAGE Warning: cannot find "Corn.dep"
+!ENDIF 
+!ENDIF 
+
+
+!IF "$(CFG)" == "Corn - Win32 Release" || "$(CFG)" == "Corn - Win32 Debug"
+SOURCE=.\corn.cpp
+
+"$(INTDIR)\corn.obj" : $(SOURCE) "$(INTDIR)"
+
+
+SOURCE=..\orange\numeric_interface.cpp
+
+"$(INTDIR)\numeric_interface.obj" : $(SOURCE) "$(INTDIR)"
+	$(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!IF  "$(CFG)" == "Corn - Win32 Release"
+
+"include - Win32 Release" : 
+   cd "\D\ai\Orange\source\include"
+   $(MAKE) /$(MAKEFLAGS) /F .\include.mak CFG="include - Win32 Release" 
+   cd "..\corn"
+
+"include - Win32 ReleaseCLEAN" : 
+   cd "\D\ai\Orange\source\include"
+   $(MAKE) /$(MAKEFLAGS) /F .\include.mak CFG="include - Win32 Release" RECURSE=1 CLEAN 
+   cd "..\corn"
+
+!ELSEIF  "$(CFG)" == "Corn - Win32 Debug"
+
+"include - Win32 Debug" : 
+   cd "\D\ai\Orange\source\include"
+   $(MAKE) /$(MAKEFLAGS) /F .\include.mak CFG="include - Win32 Debug" 
+   cd "..\corn"
+
+"include - Win32 DebugCLEAN" : 
+   cd "\D\ai\Orange\source\include"
+   $(MAKE) /$(MAKEFLAGS) /F .\include.mak CFG="include - Win32 Debug" RECURSE=1 CLEAN 
+   cd "..\corn"
+
+!ENDIF 
+
+
+!ENDIF 
+

File source/corn/Makefile

+all:	objdir $(OLD)/corn.so
+
+MODULENAME = CORN
+include ../makefile.defs
+
+obj/corn.o:	corn.cpp corn.hpp
+
+$(OLD)/corn.so:	obj/corn.o
+	$(LINKER) obj/corn.o $(LINKOPTIONS) -o $(OLD)/corn.so
+ifeq ($(OS), Darwin)
+	install_name_tool -id $(DESTDIR)/corn.so $(OLD)/corn.so
+endif
+
+clean:	cleantemp
+	rm -f $(OLD)/corn.so

File source/corn/corn.cpp

+/*
+    This file is part of Orange.
+    
+    Copyright 1996-2010 Faculty of Computer and Information Science, University of Ljubljana
+    Contact: janez.demsar@fri.uni-lj.si
+
+    Orange 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.
+
+    Orange 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 Orange.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+
+#ifdef _MSC_VER
+  #define NOMINMAX
+  #define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
+  #include <windows.h>
+#endif
+
+#include "c2py.hpp"
+#include "pywrapper.hpp"
+#include "stladdon.hpp"
+#include <vector>
+#include <map>
+#include <utility>
+#include <algorithm>
+#include <string>
+using namespace std;
+
+#include "corn.hpp"
+#include "c2py.hpp"
+
+/* *********** MODULE INITIALIZATION ************/
+
+#define PyTRY try {
+
+#define PYNULL ((PyObject *)NULL)
+#define PyCATCH   PyCATCH_r(PYNULL)
+#define PyCATCH_1 PyCATCH_r(-1)
+
+#define PyCATCH_r(r) \
+  } \
+catch (pyexception err)   { err.restore(); return r; } \
+catch (exception err) { PYERROR(PyExc_CornKernel, err.what(), r); }
+
+
+PyObject *PyExc_CornKernel;
+PyObject *PyExc_CornWarning;
+
+void initcorn()
+{ if (   ((PyExc_CornKernel = makeExceptionClass("corn.KernelException", "An error occurred in corn's C++ code")) == NULL)
+      || ((PyExc_CornWarning = makeExceptionClass("corn.Warning", "corn warning", PyExc_Warning)) == NULL))
+    return;
+
+  PyObject *me;
+  me = Py_InitModule("corn", corn_functions);
+}
+
+
+#ifdef _MSC_VER
+BOOL APIENTRY DllMain( HANDLE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
+{ switch (ul_reason_for_call)
+	{ case DLL_PROCESS_ATTACH:case DLL_THREAD_ATTACH:case DLL_THREAD_DETACH:case DLL_PROCESS_DETACH:break; }
+  return TRUE;
+}
+#endif
+
+/* *********** EXCEPTION CATCHING ETC. ************/
+
+
+#include <exception>
+#include <string>
+
+using namespace std;
+
+#ifdef _MSC_VER
+
+#define cornexception exception
+
+#else
+
+class cornexception : public exception {
+public:
+   string err_desc;
+   cornexception(const string &desc)
+   : err_desc(desc)
+   {}
+
+   ~cornexception() throw()
+   {}
+
+   virtual const char* what () const throw()
+   { return err_desc.c_str(); };
+};
+
+#endif
+
+
+exception CornException(const string &anerr)
+{ return cornexception(anerr.c_str()); }
+
+exception CornException(const string &anerr, const string &s)
+{ char buf[255];
+  sprintf(buf, anerr.c_str(), s.c_str());
+  return cornexception(buf);
+}
+
+exception CornException(const string &anerr, const string &s1, const string &s2)
+{ char buf[255];
+  sprintf(buf, anerr.c_str(), s1.c_str(), s2.c_str());
+  return cornexception(buf);
+}
+
+exception CornException(const string &anerr, const string &s1, const string &s2, const string &s3)
+{ char buf[255];
+  sprintf(buf, anerr.c_str(), s1.c_str(), s2.c_str(), s3.c_str());
+  return cornexception(buf);
+}
+
+exception CornException(const string &anerr, const long i)
+{ char buf[255];
+  sprintf(buf, anerr.c_str(), i);
+  return cornexception(buf);
+}
+
+#undef min
+#undef max
+
+#define PyTRY try {
+#define PYNULL ((PyObject *)NULL)
+
+
+int getIntegerAttr(PyObject *self, char *name, char *altername=NULL)
+{ 
+  PyObject *temp = PyObject_GetAttrString(self, name);
+
+  if (!temp && altername) {
+      PyErr_Clear();
+      temp = PyObject_GetAttrString(self, altername);
+  }
+  if (!temp)
+    throw CornException("no attribute '%s'", name);
+  if (!PyInt_Check(temp)) {
+    Py_DECREF(temp);
+    throw CornException("error in attribute '%s': integer expected", name);
+  }
+  
+  int res = (int)PyInt_AsLong(temp);
+  Py_DECREF(temp);
+  return res;
+}
+
+float getFloatAttr(PyObject *self, char *name, char *altername=NULL)
+{ 
+  PyObject *temp = PyObject_GetAttrString(self, name);
+
+  if (!temp && altername) {
+      PyErr_Clear();
+      temp = PyObject_GetAttrString(self, altername);
+  }
+  if (!temp)
+    throw CornException("no attribute '%s'", name);
+  if (!PyFloat_Check(temp)) {
+    Py_DECREF(temp);
+    throw CornException("error in attribute '%s': float expected", name);
+  }
+
+  float res = (float)PyFloat_AsDouble(temp);
+  Py_DECREF(temp);
+  return res;
+}
+
+
+
+class TestedExample {
+public:
+  int actualClass;
+  int iterationNumber;
+  vector<int> classes;
+  vector<vector<float> > probabilities;
+  float weight;
+
+  TestedExample(const int &ac, const int &it, const vector<int> &c, const vector<vector<float> > &p, const float &w = 1.0);
+  TestedExample(PyObject *);
+};
+
+
+class ExperimentResults {
+public:
+  int numberOfIterations, numberOfLearners, numberOfClasses;
+  vector<TestedExample> results;
+  bool weights;
+  int baseClass;
+
+  ExperimentResults(const int &ni, const int &nl, const int &nc, const bool &);
+  ExperimentResults(PyObject *);
+};
+
+
+
+TestedExample::TestedExample(const int &ac, const int &it, const vector<int> &c, const vector<vector<float> > &p, const float &w)
+: actualClass(ac),
+  iterationNumber(it),
+  classes(c),
+  probabilities(p),
+  weight(w)
+{}
+
+
+TestedExample::TestedExample(PyObject *obj)
+: actualClass(getIntegerAttr(obj, "actualClass", "actual_class")),
+  iterationNumber(getIntegerAttr(obj, "iteration_number", "iterationNumber")),
+  weight(getFloatAttr(obj, "weight"))
+
+{ 
+  PyObject *temp = PYNULL;
+
+  try {
+    temp = PyObject_GetAttrString(obj, "classes");
+    if (!temp || !PyList_Check(temp))
+      throw CornException("error in 'classes' attribute");
+
+    int i,e;
+    for(i = 0, e = PyList_Size(temp); i<e; i++) {
+      PyObject *cp = PyList_GetItem(temp, i);
+      if (!cp || !PyInt_Check(cp))
+        throw CornException("error in attribute 'classes'");
+      classes.push_back((int)PyInt_AsLong(cp));
+    }
+    Py_DECREF(temp);
+    temp = PYNULL;
+
+    temp = PyObject_GetAttrString(obj, "probabilities");
+    if (!temp || !PyList_Check(temp))
+      throw CornException("error in attribute 'probabilities'");
+  
+    for(i = 0, e = PyList_Size(temp); i<e; i++) {
+      PyObject *slist = PyList_GetItem(temp, i);
+      if (!slist || !PyList_Check(slist))
+        throw CornException("error in 'probabilities' attribute");
+      
+      probabilities.push_back(vector<float>());
+      for(Py_ssize_t ii = 0, ee = PyList_Size(slist); ii<ee; ii++) {
+        PyObject *fe = PyList_GetItem(slist, ii);
+        if (!fe || !PyFloat_Check(fe))
+          throw CornException("error in 'probabilities' attribute");
+        probabilities.back().push_back((float)PyFloat_AsDouble(fe));
+      }
+    }
+
+    Py_DECREF(temp);
+    temp = PYNULL;
+  }
+  catch (...) {
+    Py_XDECREF(temp);
+  }
+}
+        
+      
+
+ExperimentResults::ExperimentResults(const int &ni, const int &nl, const int &nc, const bool &w)
+: numberOfIterations(ni),
+  numberOfLearners(nl),
+  numberOfClasses(nc),
+  weights(w)
+{}
+
+
+ExperimentResults::ExperimentResults(PyObject *obj)
+: numberOfIterations(getIntegerAttr(obj, "numberOfIterations", "number_of_iterations")),
+  numberOfLearners(getIntegerAttr(obj, "numberOfLearners", "number_of_learners"))
+{ 
+  PyObject *temp = PyObject_GetAttrString(obj, "weights");
+  weights = temp && (PyObject_IsTrue(temp)!=0);
+  Py_XDECREF(temp);
+
+  temp = PyObject_GetAttrString(obj, "baseClass");
+  PyErr_Clear();
+  if (!temp)
+      temp = PyObject_GetAttrString(obj, "base_class");
+  baseClass = temp ? PyInt_AsLong(temp) : -1;
+  Py_XDECREF(temp);
+
+  temp = PyObject_GetAttrString(obj, "classValues");
+  PyErr_Clear();
+  if (!temp)
+      temp = PyObject_GetAttrString(obj, "class_values");
+  if (!temp)
+    throw CornException("no 'classValues' attribute");
+  numberOfClasses = PySequence_Size(temp);
+  Py_DECREF(temp);
+  if (numberOfClasses == -1)
+    throw CornException("'classValues' should contain a list of class names");
+
+  PyObject *pyresults = PyObject_GetAttrString(obj, "results");
+  if (!pyresults)
+    throw CornException("no 'results' attribute");
+
+  if (!PyList_Check(pyresults)) {
+    Py_DECREF(pyresults);
+    throw CornException("'results' is no a list");
+  }
+
+  for(Py_ssize_t i = 0, e = PyList_Size(pyresults); i<e; i++) {
+    PyObject *testedExample = PyList_GetItem(pyresults, i);
+    results.push_back(TestedExample(testedExample));
+  }
+
+  Py_DECREF(pyresults);
+}
+
+
+
+inline float diff2(const float &abnormal, const float &normal)
+{ if (normal<abnormal)
+    return 1;
+  if (normal>abnormal)
+    return 0;
+  return 0.5;
+}
+
+
+
+
+class pp {
+public:
+  float normal, abnormal;
+
+  inline pp()
+  : normal(0.0),
+    abnormal(0.0)
+  {}
+
+  inline void add(const bool &b, const float &w = 1.0)
+  { *(b ? &abnormal : &normal) += w; }
+
+  pp &operator +=(const pp &other)
+  { normal += other.normal;
+    abnormal += other.abnormal;
+    return *this;
+  }
+
+  pp &operator -=(const pp &other)
+  { normal -= other.normal;
+    abnormal -= other.abnormal;
+    return *this;
+  }
+};
+
+typedef map<float, pp> TCummulativeROC;
+
+void C_computeROCCumulative(const ExperimentResults &results, int classIndex, pp &totals, vector<TCummulativeROC> &cummlists, bool useWeights)
+{
+  if (classIndex<0)
+    classIndex = results.baseClass;
+  if (classIndex<0)
+    classIndex = 1;
+  if (classIndex >= results.numberOfClasses)
+    throw CornException("classIndex out of range");
+
+  totals = pp();
+  cummlists = vector<TCummulativeROC>(results.numberOfLearners);
+
+  const_ITERATE(vector<TestedExample>, i, results.results) {
+    bool ind = (*i).actualClass==classIndex;
+    float weight = useWeights ? (*i).weight : 1.0;
+    totals.add(ind, weight);
+
+    vector<TCummulativeROC>::iterator ci(cummlists.begin());
+    const_ITERATE(vector<vector<float> >, pi, (*i).probabilities) {
+      const float &tp = (*pi)[classIndex];
+      (*ci)[tp];
+      (*ci)[tp].add(ind, weight);
+      ci++;
+    }
+  }
+}
+
+
+void C_computeROCCumulativePair(const ExperimentResults &results, int classIndex1, int classIndex2, pp &totals, vector<TCummulativeROC> &cummlists, bool useWeights)
+{
+  if ((classIndex1 >= results.numberOfClasses) || (classIndex2 >= results.numberOfClasses))
+    throw CornException("classIndex out of range");
+
+  totals = pp();
+  cummlists = vector<TCummulativeROC>(results.numberOfLearners);
+
+  const_ITERATE(vector<TestedExample>, i, results.results) {
+    bool ind = (*i).actualClass==classIndex1;
+    if (!ind && ((*i).actualClass!=classIndex2))
+      continue;
+
+    float weight = useWeights ? (*i).weight : 1.0;
+    totals.add(ind, weight);
+
+    vector<TCummulativeROC>::iterator ci(cummlists.begin());
+    const_ITERATE(vector<vector<float> >, pi, (*i).probabilities) {
+      const float &c1 = (*pi)[classIndex1];
+      const float c_sum = c1 + (*pi)[classIndex2];
+      const float tp = (c_sum > 1e-10) ? c1 / c_sum : 0.5;
+      (*ci)[tp];
+      (*ci)[tp].add(ind, weight);
+      ci++;
+    }
+  }
+}
+
+
+class TCDT {
+public:
+  float C, D, T;
+  TCDT()
+  : C(0.0),
+    D(0.0),
+    T(0.0)
+  {}
+};
+
+void C_computeCDT(const vector<TCummulativeROC> &cummlists, vector<TCDT> &cdts)
+{
+  cdts = vector<TCDT>(cummlists.size());
+  
+  vector<TCDT>::iterator cdti (cdts.begin());
+  for (vector<TCummulativeROC>::const_iterator ci(cummlists.begin()), ce(cummlists.end()); ci!=ce; ci++, cdti++) {
+    pp low;
+    for (map<float, pp>::const_iterator cri((*ci).begin()), cre((*ci).end()); cri!=cre; cri++) {
+      const pp &thi = (*cri).second;
+      (*cdti).C += low.normal   * thi.abnormal;
+      (*cdti).D += low.abnormal * thi.normal;
+      (*cdti).T += thi.normal   * thi.abnormal;
+      low += thi;
+    }
+  }
+}
+
+
+PyObject *py_ROCCumulativeList(vector<TCummulativeROC> &cummlists, pp &totals)
+{
+  PyObject *pyresults = PyList_New(cummlists.size());
+  int lrn = 0;
+  ITERATE(vector<TCummulativeROC>, ci, cummlists) {
+    PyObject *pclist = PyList_New((*ci).size());
+    int prb = 0;
+    ITERATE(TCummulativeROC, si, *ci)
+      PyList_SetItem(pclist, prb++, Py_BuildValue("f(ff)", (*si).first, (*si).second.normal, (*si).second.abnormal));
+    PyList_SetItem(pyresults, lrn++, pclist);
+  }
+
+  return Py_BuildValue("N(ff)", pyresults, totals.normal, totals.abnormal);
+}
+
+
+PyObject *py_computeROCCumulative(PyObject *, PyObject *arg)
+{ 
+  PyTRY
+    PyObject *pyresults;
+    int classIndex = -1;
+    PyObject *pyuseweights = NULL;
+    if (!PyArg_ParseTuple(arg, "O|iO", &pyresults, &classIndex, &pyuseweights))
+      PYERROR(PyExc_TypeError, "computeROCCummulative: results and optionally the classIndex and 'useWeights' flag expected", PYNULL);
+
+    bool useweights = pyuseweights && PyObject_IsTrue(pyuseweights)!=0;
+
+    ExperimentResults results(pyresults);
+    if (results.numberOfIterations>1)
+      PYERROR(PyExc_SystemError, "computeCDT: cannot compute CDT for experiments with multiple iterations", PYNULL);
+
+
+    pp totals;
+    vector<TCummulativeROC> cummlists;
+    C_computeROCCumulative(results, classIndex, totals, cummlists, useweights);
+    return py_ROCCumulativeList(cummlists, totals);
+  PyCATCH
+}
+
+
+PyObject *py_computeROCCumulativePair(PyObject *, PyObject *arg)
+{ 
+  PyTRY
+    PyObject *pyresults;
+    int classIndex1, classIndex2;
+    PyObject *pyuseweights = NULL;
+    if (!PyArg_ParseTuple(arg, "Oii|O", &pyresults, &classIndex1, &classIndex2, &pyuseweights))
+      PYERROR(PyExc_TypeError, "computeROCCummulative: results and classIndices, and optional 'useWeights' flag expected", PYNULL);
+
+    bool useweights = pyuseweights && PyObject_IsTrue(pyuseweights)!=0;
+
+    ExperimentResults results(pyresults);
+    if (results.numberOfIterations>1)
+      PYERROR(PyExc_SystemError, "computeCDT: cannot compute CDT for experiments with multiple iterations", PYNULL);
+
+
+    pp totals;
+    vector<TCummulativeROC> cummlists;
+    C_computeROCCumulativePair(results, classIndex1, classIndex2, totals, cummlists, useweights);
+    return py_ROCCumulativeList(cummlists, totals);
+  PyCATCH
+}
+
+
+PyObject *computeCDTList(vector<TCummulativeROC> &cummlists)
+{
+  PyObject *res = NULL, *orngStatModule = NULL;
+
+  try {
+    vector<TCDT> cdts;
+    C_computeCDT(cummlists, cdts);
+
+    PyObject *orngStatModule = PyImport_ImportModule("orngStat");
+    if (!orngStatModule)
+      return PYNULL;
+
+    // PyModule_GetDict and PyDict_GetItemString return borrowed references
+    PyObject *orngStatModuleDict = PyModule_GetDict(orngStatModule);
+    Py_DECREF(orngStatModule);
+    orngStatModule = NULL;
+
+    PyObject *CDTType = PyDict_GetItemString(orngStatModuleDict, "CDT");
+
+    if (!CDTType)
+      PYERROR(PyExc_AttributeError, "orngStat does not define CDT class", PYNULL);
+
+    PyObject *res = PyList_New(cdts.size());
+    int i = 0;
+    ITERATE(vector<TCDT>, cdti, cdts) {
+      PyObject *inargs = Py_BuildValue("fff", (*cdti).C, (*cdti).D, (*cdti).T);
+      PyObject *indict = PyDict_New();
+      PyObject *PyCDT = PyInstance_New(CDTType, inargs, indict);
+      Py_DECREF(inargs);
+      Py_DECREF(indict);
+
+      if (!PyCDT) {
+        Py_XDECREF(res);
+        return PYNULL;
+      }
+      PyList_SetItem(res, i++, PyCDT);
+    }
+
+    return res;
+  }
+  catch (...) {
+    Py_XDECREF(res);
+    Py_XDECREF(orngStatModule);
+    throw;
+  }
+}
+
+
+PyObject *py_computeCDT(PyObject *, PyObject *arg)
+{
+  PyTRY
+    PyObject *pyresults;
+    int classIndex = -1;
+    PyObject *pyuseweights = PYNULL;
+    if (!PyArg_ParseTuple(arg, "O|iO", &pyresults, &classIndex, &pyuseweights))
+      PYERROR(PyExc_TypeError, "computeROCCummulative: results and optionally the classIndex expected", PYNULL);
+
+    bool useweights = pyuseweights && PyObject_IsTrue(pyuseweights)!=0;
+
+    ExperimentResults results(pyresults);
+
+    pp totals;
+    vector<TCummulativeROC> cummlists;
+    C_computeROCCumulative(results, classIndex, totals, cummlists, useweights);
+
+    return computeCDTList(cummlists);
+  PyCATCH
+}
+
+
+PyObject *py_computeCDTPair(PyObject *, PyObject *arg)
+{
+  PyTRY
+    PyObject *pyresults;
+    int classIndex1, classIndex2;
+    PyObject *pyuseweights = PYNULL;
+    if (!PyArg_ParseTuple(arg, "Oii|O", &pyresults, &classIndex1, &classIndex2, &pyuseweights))
+      PYERROR(PyExc_TypeError, "computeROCCummulative: results, two class indices and optional flag for using weights", PYNULL);
+
+    bool useweights = pyuseweights && PyObject_IsTrue(pyuseweights)!=0;
+
+    ExperimentResults results(pyresults);
+
+    pp totals;
+    vector<TCummulativeROC> cummlists;
+    C_computeROCCumulativePair(results, classIndex1, classIndex2, totals, cummlists, useweights);
+
+    return computeCDTList(cummlists);
+  PyCATCH
+}
+
+
+PyObject *py_compare2ROCs(PyObject *, PyObject *arg)
+{ PyTRY
+    PyObject *pyresults;
+    int roc1, roc2, classIndex = -1;
+    PyObject *pyuseweights;
+    if (!PyArg_ParseTuple(arg, "OiiiO", &pyresults, &roc1, &roc2, &classIndex, &pyuseweights))
+      PYERROR(PyExc_TypeError, "compare2ROCs: results and two integer indices (optionally also classIndex) expected", PYNULL);
+
+    bool useweights = PyObject_IsTrue(pyuseweights)!=0;
+    if (useweights)
+      PYERROR(PyExc_SystemError, "compare2ROCs: cannot use weights (weights not implemented yet)", PYNULL);
+
+    ExperimentResults results(pyresults);
+    if (results.numberOfIterations>1)
+      PYERROR(PyExc_SystemError, "computeCDT: cannot compute CDT for experiments with multiple iterations", PYNULL);
+
+    if (classIndex<0)
+      classIndex = results.baseClass;
+    if (classIndex<0)
+      classIndex = 1;
+
+    float e11[] = {0, 0}, e10[] = {0, 0}, e01[] = {0, 0};
+    float e11r = 0, e10r = 0, e01r = 0;
+    float th[] ={0, 0};
+    int m = 0, n = 0;
+    /* m is number of examples with class == classIndex, n are others
+       X_* represent example with class == classIndex, Y_* are others
+    */
+
+    for (vector<TestedExample>::const_iterator i(results.results.begin()), e(results.results.end()); i!=e; i++)
+      if ((*i).actualClass != classIndex) {
+        n++;
+      }
+      else { // (*i).actualClass == classIndex
+        m++;
+
+        float X_i[] = {(*i).probabilities[roc1][classIndex], (*i).probabilities[roc2][classIndex]};
+
+        for (vector<TestedExample>::const_iterator j = i+1; j!=e; j++)
+          if ((*j).actualClass!=classIndex) {
+
+            float Y_j[] = {(*j).probabilities[roc1][classIndex], (*j).probabilities[roc2][classIndex]};
+            float diffs[] = { diff2(X_i[0], Y_j[0]), diff2(X_i[1], Y_j[1]) };
+
+            th[0] += diffs[0];
+            th[1] += diffs[1];
+
+            e11[0] += sqr(diffs[0]);
+            e11[1] += sqr(diffs[1]);
+            e11r   += diffs[0]*diffs[1];
+
+            for (vector<TestedExample>::const_iterator k = j+1; k!=e; k++)
+              if ((*k).actualClass == classIndex) { // B_XXY
+                float X_k[] = { (*k).probabilities[roc1][classIndex], (*k).probabilities[roc2][classIndex] };
+                float diffsk[] = { diff2(X_k[0], Y_j[0]), diff2(X_k[1], Y_j[1]) };
+                e01[0] += diffs[0]*diffsk[0];
+                e01[1] += diffs[1]*diffsk[1];
+                e01r   += diffs[0]*diffsk[1] + diffs[1]*diffsk[0];
+              }
+              else { // B_XYY
+                float Y_k[] = { (*k).probabilities[roc1][classIndex], (*k).probabilities[roc2][classIndex] };
+                float diffsk[] = { diff2(X_i[0], Y_k[0]), diff2(X_i[1], Y_k[1]) };
+                e10[0] += diffs[0]*diffsk[0];
+                e10[1] += diffs[1]*diffsk[1];
+                e10r   += diffs[0]*diffsk[1] + diffs[1]*diffsk[0];
+              }
+          }
+      }
+
+    float n11 = float(m)*float(n), n01 = float(m)*float(n)*float(m-1)/2.0, n10 = float(m)*float(n)*float(n-1)/2.0;
+  
+    th[0] /= n11;
+    th[1] /= n11;
+    
+    e11[0] = e11[0]/n11 - sqr(th[0]);
+    e11[1] = e11[1]/n11 - sqr(th[1]);
+    e11r   = e11r  /n11 - th[0]*th[1];
+
+    e10[0] = e10[0]/n10 - sqr(th[0]);
+    e10[1] = e10[1]/n10 - sqr(th[1]);
+    e10r   = e10r  /n10 - th[0]*th[1];
+
+    e01[0] = e01[0]/n01 - sqr(th[0]);
+    e01[1] = e01[1]/n01 - sqr(th[1]);
+    e01r   = e01r  /n01 - th[0]*th[1];
+
+    float var[] = { ((n-1)*e10[0] + (m-1)*e01[0] + e11[0])/n11, ((n-1)*e10[1] + (m-1)*e01[1] + e11[1])/n11};
+    float SE[]  = { sqrt(var[0]), sqrt(var[1]) };
+
+    float covar = ((n-1)*e10r + (m-1)*e01r + e11r) / n11;
+    float SEr   = sqrt(var[0]+var[1]-2*covar*SE[0]*SE[1]);
+
+    return Py_BuildValue("(ff)(ff)(ff)", th[0], SE[0], th[1], SE[1], th[0]-th[1], SEr);
+  PyCATCH
+}
+
+
+inline float cmphalf(const float &x, const float &y)
+{
+  if (x<y)   return 0;
+  if (x==y)  return 0.25;
+  return 0.5;
+}
+
+PyObject *py_mAUC(PyObject *, PyObject *arg)
+{ PyTRY
+    PyObject *pyresults;
+    PyObject *pyuseweights = PYNULL;
+    if (!PyArg_ParseTuple(arg, "O|O:corn.mAUC", &pyresults, &pyuseweights))
+      PYERROR(PyExc_TypeError, "mAUC: results and optionally use weights flag expected", PYNULL);
+
+    bool useweights = pyuseweights && (PyObject_IsTrue(pyuseweights)!=0);
+    if (useweights)
+      PYERROR(PyExc_SystemError, "mAUC: cannot use weights (weights not implemented yet)", PYNULL);
+
+    ExperimentResults results(pyresults);
+/*    if (results.numberOfIterations>1)
+      PYERROR(PyExc_SystemError, "mAUC: cannot compute CDT for experiments with multiple iterations", PYNULL);
+*/
+
+    const int nLearners = results.numberOfLearners;
+    vector<float> correctPairs(nLearners, 0.0);
+    int usefulPairs = 0;
+
+    for (vector<TestedExample>::const_iterator i1(results.results.begin()), e(results.results.end()); i1!=e; i1++)
+      for (vector<TestedExample>::const_iterator i2(i1); i2!=e; i2++) {
+        const int cls1 = (*i1).actualClass;
+        const int cls2 = (*i2).actualClass;
+        if (cls1 != cls2) {
+          usefulPairs++;
+          vector<float>::iterator cpi(correctPairs.begin());
+          vector<vector<float> >::const_iterator ep1i((*i1).probabilities.begin()), ep2i((*i2).probabilities.begin());
+          for(int cfr = nLearners; cfr--; cpi++, ep1i++, ep2i++)
+            *cpi +=  cmphalf((*ep1i)[cls1], (*ep2i)[cls1])
+                   + cmphalf((*ep2i)[cls2], (*ep1i)[cls2]);
+        }
+      }
+
+    PyObject *res = PyList_New(nLearners);
+    for(int cfr = 0; cfr<nLearners; cfr++)
+      PyList_SetItem(res, cfr, PyFloat_FromDouble(correctPairs[cfr]/usefulPairs));
+    return res;
+  PyCATCH
+}
+
+/* *********** AUXILIARY ROUTINES *************/
+
+class CompCallbackLess {
+public:
+  PyObject *py_compare;
+
+  CompCallbackLess(PyObject *apyc)
+    : py_compare(apyc)
+    { Py_XINCREF(apyc); }
+
+  ~CompCallbackLess()
+    { Py_XDECREF(py_compare); }
+
+  int operator()(PyObject *obj1, PyObject *obj2)
+    { PyObject *args = Py_BuildValue("OO", obj1, obj2);
+      PyObject *result = PyEval_CallObject(py_compare, args);
+      Py_DECREF(args);
+
+      if (!result) 
+        throw pyexception();
+
+      bool res = PyInt_AsLong(result)<0;
+      Py_DECREF(result);
+      return res;
+    }
+};
+
+
+class CompCallbackEqual {
+public:
+  PyObject *py_compare;
+
+  CompCallbackEqual(PyObject *apyc)
+    : py_compare(apyc)
+    { Py_XINCREF(apyc); }
+
+  ~CompCallbackEqual()
+    { Py_XDECREF(py_compare); }
+
+  int operator()(PyObject *obj1, PyObject *obj2)
+    { PyObject *args = Py_BuildValue("OO", obj1, obj2);
+      PyObject *result = PyEval_CallObject(py_compare, args);
+      Py_DECREF(args);
+
+      if (!result) 
+        throw pyexception();
+
+      bool res = (PyInt_AsLong(result)==0);
+      Py_DECREF(result);
+      return res;
+    }
+};
+
+    
+
+/* *********** EXPORT DECLARATIONS ************/
+
+#define DECLARE(name) \
+ {#name, (binaryfunc)py_##name, METH_VARARGS},
+
+PyMethodDef corn_functions[] = {
+     DECLARE(compare2ROCs)
+     DECLARE(computeROCCumulative)
+     DECLARE(computeROCCumulativePair)
+     DECLARE(computeCDT)
+     DECLARE(computeCDTPair)
+     DECLARE(mAUC)
+
+
+     {NULL, NULL}
+};
+
+#undef DECLARE
+
+#undef PyTRY
+#undef PyCATCH
+#undef PYNULL

File source/corn/corn.hpp

+/*
+    This file is part of Orange.
+    
+    Copyright 1996-2010 Faculty of Computer and Information Science, University of Ljubljana
+    Contact: janez.demsar@fri.uni-lj.si
+
+    Orange 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.
+
+    Orange 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 Orange.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+
+#ifdef _MSC_VER
+  #ifdef CORN_EXPORTS
+    #define CORN_API __declspec(dllexport)
+  #else
+    #define CORN_API __declspec(dllimport)
+  #endif
+#else
+  #define CORN_API
+#endif
+
+
+#include "c2py.hpp"
+
+extern "C" CORN_API void initcorn(void);
+extern PyMethodDef corn_functions[];
+

File source/corn/corn.vcproj

+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="9.00"
+	Name="Corn"
+	ProjectGUID="{DB7466D1-CF93-44A1-9AB2-27290A2EC7C7}"
+	RootNamespace="Corn"
+	TargetFrameworkVersion="131072"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Release|Win32"
+			ConfigurationType="2"
+			InheritedPropertySheets="..\orange.vsprops"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				PreprocessorDefinitions="NDEBUG"
+				MkTypLibCompatible="true"
+				SuppressStartupBanner="true"
+				TargetEnvironment="1"
+				TypeLibraryName=".\obj/Release/Corn.tlb"
+				HeaderFileName=""
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalIncludeDirectories=""
+				PreprocessorDefinitions="CORN_EXPORTS"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="NDEBUG"
+				Culture="1033"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="orange.lib"
+				OutputFile="$(PYTHON)/lib/site-packages/orange/corn.pyd"
+				AdditionalLibraryDirectories=""
+				RandomizedBaseAddress="1"
+				DataExecutionPrevention="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+				CommandLine=""
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|Win32"
+			ConfigurationType="2"
+			InheritedPropertySheets="..\orange.vsprops"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				PreprocessorDefinitions="_DEBUG"
+				MkTypLibCompatible="true"
+				SuppressStartupBanner="true"
+				TargetEnvironment="1"
+				TypeLibraryName=".\obj/Debug/Corn.tlb"
+				HeaderFileName=""
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories=""
+				PreprocessorDefinitions="_DEBUG;CORN_EXPORTS"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_DEBUG"
+				Culture="1033"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="orange_d.lib"
+				OutputFile="$(PYTHON)/lib/site-packages/orange/corn_d.pyd"
+				AdditionalLibraryDirectories=""
+				GenerateDebugInformation="true"
+				RandomizedBaseAddress="1"
+				DataExecutionPrevention="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>