<commit_before>package libsvm

import (
	"bufio"
	"log"
	"math"
	"math/rand"
	"os"
	"strconv"
)

type headT struct {
	prev, next *headT
	data       []float32
	length     int
}

// Cache for svm
type Cache struct {
	l       int
	size    int64
	head    []*headT
	lruHead *headT
}

// NewCache create cache
func NewCache(l int, size int64) *Cache {
	m := new(Cache)
	m.l = l
	m.size = size
	m.head = make([]*headT, m.l)
	for i := 0; i < m.l; i++ {
		m.head[i] = new(headT)
	}
	m.size /= 4
	m.size -= int64(m.l * (16 / 4))                           // sizeof(headT) == 16
	m.size = int64(math.Max(float64(m.size), float64(2*m.l))) // cache must be large enough for two columns
	m.lruHead = new(headT)
	m.lruHead.prev = m.lruHead
	m.lruHead.next = m.lruHead.prev
	return m
}

func (m *Cache) lruDelete(h *headT) {
	// delete from current location
	h.prev.next = h.next
	h.next.prev = h.prev
}
func (m *Cache) lruInsert(h *headT) {
	// insert to last position
	h.next = m.lruHead
	h.prev = m.lruHead.prev
	h.prev.next = h
	h.next.prev = h
}

// request data [0,length)
// return some position p where [p,length) need to be filled
// (p >= length if nothing needs to be filled)
// java: simulate pointer using single-element array

func (m *Cache) getData(index int, data [][]float32, length int) int {
	h := m.head[index]
	if h.length > 0 {
		m.lruDelete(h)
	}
	more := length - h.length
	if more > 0 {
		// free old space
		for m.size < int64(more) {
			old := m.lruHead.next
			m.lruDelete(old)
			m.size += int64(old.length)
			old.data = nil
			old.length = 0
		}

		// allocate new space
		newData := make([]float32, length)
		if h.data != nil {
			// System.arraycopy(h.data,0,newData,0,h.length)
			copy(newData, h.data[:length])
		}
		h.data = newData
		m.size -= int64(more)
		// do {int _=h.length; h.length=length; length=_;} while(false);
		h.length, length = length, h.length
	}

	m.lruInsert(h)
	data[0] = h.data
	return length
}

func (m *Cache) swapIndex(i, j int) {
	if i == j {
		return
	}

	if m.head[i].length > 0 {
		m.lruDelete(m.head[i])
	}
	if m.head[j].length > 0 {
		m.lruDelete(m.head[j])
	}
	//do {float32[] _=head[i].data; head[i].data=head[j].data; head[j].data=_;} while(false);
	m.head[i].data, m.head[j].data = m.head[j].data, m.head[i].data
	//do {int _=head[i].length; head[i].length=head[j].length; head[j].length=_;} while(false);
	m.head[i].length, m.head[j].length = m.head[j].length, m.head[i].length

	if m.head[i].length > 0 {
		m.lruInsert(m.head[i])
	}
	if m.head[j].length > 0 {
		m.lruInsert(m.head[j])
	}

	if i > j {
		//do {int _=i; i=j; j=_;} while(false);
		i, j = j, i
	}
	for h := m.lruHead.next; h != m.lruHead; h = h.next {
		if h.length > i {
			if h.length > j {
				//do {float32 _=h.data[i]; h.data[i]=h.data[j]; h.data[j]=_;} while(false);
				h.data[i], h.data[j] = h.data[j], h.data[i]
			} else {
				// give up
				m.lruDelete(h)
				m.size += int64(h.length)
				h.data = nil
				h.length = 0
			}
		}
	}
}

// QMatrix define qmatrix interface
type QMatrix interface {
	swapIndex(i, j int)
	getQ(column, length int) []float32
	getQD() []float64
}

// Kernel struct
type Kernel struct {
	x          [][]SVMNode
	xSquare    []float64
	kernelType int
	degree     int
	gamma      float64
	coef0      float64
}

func (m *Kernel) swapIndex(i, j int) {
	m.x[i], m.x[j] = m.x[j], m.x[i]
	if m.xSquare != nil {
		m.xSquare[i], m.xSquare[j] = m.xSquare[j], m.xSquare[i]
	}
}

func powi(base float64, times int) float64 {
	tmp := base
	ret := 1.0

	for t := times; t > 0; t /= 2 {
		if t%2 == 1 {
			ret *= tmp
		}
		tmp = tmp * tmp
	}
	return ret
}

func (m *Kernel) kernelFunction(i, j int) float64 {
	switch m.kernelType {
	case LINEAR:
		return dot(m.x[i], m.x[j])
	case POLY:
		return powi(m.gamma*dot(m.x[i], m.x[j])+m.coef0, m.degree)
	case RBF:
		return math.Exp(-m.gamma * (m.xSquare[i] + m.xSquare[j] - 2*dot(m.x[i], m.x[j])))
	case SIGMOID:
		return math.Tanh(m.gamma*dot(m.x[i], m.x[j]) + m.coef0)
	case PRECOMPUTED:
		return m.x[i][int(m.x[j][0].Value)].Value
	}
	return 0
}

// NewKernel create kernel from give svmnode
func NewKernel(l int, x [][]SVMNode, param *SVMParameter) *Kernel {
	m := new(Kernel)
	m.kernelType = param.KernelType
	m.degree = param.Degree
	m.gamma = param.Gamma
	m.coef0 = param.Coef0
	// x.clone
	copy(m.x, x)

	if m.kernelType == RBF {
		m.xSquare = make([]float64, l)
		for i := 0; i < l; i++ {
			m.xSquare[i] = dot(m.x[i], m.x[i])
		}
	} else {
		m.xSquare = nil
	}
	return m
}

func dot(x, y []SVMNode) float64 {<commit_msg>Fix error when copying Nodes to Kernel<commit_after>package libsvm

import (
	"bufio"
	"log"
	"math"
	"math/rand"
	"os"
	"strconv"
)

type headT struct {
	prev, next *headT
	data       []float32
	length     int
}

// Cache for svm
type Cache struct {
	l       int
	size    int64
	head    []*headT
	lruHead *headT
}

// NewCache create cache
func NewCache(l int, size int64) *Cache {
	m := new(Cache)
	m.l = l
	m.size = size
	m.head = make([]*headT, m.l)
	for i := 0; i < m.l; i++ {
		m.head[i] = new(headT)
	}
	m.size /= 4
	m.size -= int64(m.l * (16 / 4))                           // sizeof(headT) == 16
	m.size = int64(math.Max(float64(m.size), float64(2*m.l))) // cache must be large enough for two columns
	m.lruHead = new(headT)
	m.lruHead.prev = m.lruHead
	m.lruHead.next = m.lruHead.prev
	return m
}

func (m *Cache) lruDelete(h *headT) {
	// delete from current location
	h.prev.next = h.next
	h.next.prev = h.prev
}
func (m *Cache) lruInsert(h *headT) {
	// insert to last position
	h.next = m.lruHead
	h.prev = m.lruHead.prev
	h.prev.next = h
	h.next.prev = h
}

// request data [0,length)
// return some position p where [p,length) need to be filled
// (p >= length if nothing needs to be filled)
// java: simulate pointer using single-element array

func (m *Cache) getData(index int, data [][]float32, length int) int {
	h := m.head[index]
	if h.length > 0 {
		m.lruDelete(h)
	}
	more := length - h.length
	if more > 0 {
		// free old space
		for m.size < int64(more) {
			old := m.lruHead.next
			m.lruDelete(old)
			m.size += int64(old.length)
			old.data = nil
			old.length = 0
		}

		// allocate new space
		newData := make([]float32, length)
		if h.data != nil {
			// System.arraycopy(h.data,0,newData,0,h.length)
			copy(newData, h.data[:length])
		}
		h.data = newData
		m.size -= int64(more)
		// do {int _=h.length; h.length=length; length=_;} while(false);
		h.length, length = length, h.length
	}

	m.lruInsert(h)
	data[0] = h.data
	return length
}

func (m *Cache) swapIndex(i, j int) {
	if i == j {
		return
	}

	if m.head[i].length > 0 {
		m.lruDelete(m.head[i])
	}
	if m.head[j].length > 0 {
		m.lruDelete(m.head[j])
	}
	//do {float32[] _=head[i].data; head[i].data=head[j].data; head[j].data=_;} while(false);
	m.head[i].data, m.head[j].data = m.head[j].data, m.head[i].data
	//do {int _=head[i].length; head[i].length=head[j].length; head[j].length=_;} while(false);
	m.head[i].length, m.head[j].length = m.head[j].length, m.head[i].length

	if m.head[i].length > 0 {
		m.lruInsert(m.head[i])
	}
	if m.head[j].length > 0 {
		m.lruInsert(m.head[j])
	}

	if i > j {
		//do {int _=i; i=j; j=_;} while(false);
		i, j = j, i
	}
	for h := m.lruHead.next; h != m.lruHead; h = h.next {
		if h.length > i {
			if h.length > j {
				//do {float32 _=h.data[i]; h.data[i]=h.data[j]; h.data[j]=_;} while(false);
				h.data[i], h.data[j] = h.data[j], h.data[i]
			} else {
				// give up
				m.lruDelete(h)
				m.size += int64(h.length)
				h.data = nil
				h.length = 0
			}
		}
	}
}

// QMatrix define qmatrix interface
type QMatrix interface {
	swapIndex(i, j int)
	getQ(column, length int) []float32
	getQD() []float64
}

// Kernel struct
type Kernel struct {
	x          [][]SVMNode
	xSquare    []float64
	kernelType int
	degree     int
	gamma      float64
	coef0      float64
}

func (m *Kernel) swapIndex(i, j int) {
	m.x[i], m.x[j] = m.x[j], m.x[i]
	if m.xSquare != nil {
		m.xSquare[i], m.xSquare[j] = m.xSquare[j], m.xSquare[i]
	}
}

func powi(base float64, times int) float64 {
	tmp := base
	ret := 1.0

	for t := times; t > 0; t /= 2 {
		if t%2 == 1 {
			ret *= tmp
		}
		tmp = tmp * tmp
	}
	return ret
}

func (m *Kernel) kernelFunction(i, j int) float64 {
	switch m.kernelType {
	case LINEAR:
		return dot(m.x[i], m.x[j])
	case POLY:
		return powi(m.gamma*dot(m.x[i], m.x[j])+m.coef0, m.degree)
	case RBF:
		return math.Exp(-m.gamma * (m.xSquare[i] + m.xSquare[j] - 2*dot(m.x[i], m.x[j])))
	case SIGMOID:
		return math.Tanh(m.gamma*dot(m.x[i], m.x[j]) + m.coef0)
	case PRECOMPUTED:
		return m.x[i][int(m.x[j][0].Value)].Value
	}
	return 0
}

// NewKernel create kernel from give svmnode
func NewKernel(l int, x [][]SVMNode, param *SVMParameter) *Kernel {
	m := new(Kernel)
	m.kernelType = param.KernelType
	m.degree = param.Degree
	m.gamma = param.Gamma
	m.coef0 = param.Coef0
	// x.clone
	m.x = make([][]SVMNode, len(x))
	copy(m.x, x)

	if m.kernelType == RBF {
		m.xSquare = make([]float64, l)
		for i := 0; i < l; i++ {
			m.xSquare[i] = dot(m.x[i], m.x[i])
		}
	} else {
		m.xSquare = nil
	}
	return m
}

func dot(x, y []SVMNode) float64 {
{'fraction_non_alphanumeric': 0.18444786625604928, 'fraction_numerical': 0.01869775626924769, 'mean_word_length': 2.7714641227706345, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3640674', 'n_tokens_mistral': 4343, 'n_tokens_neox': 4057, 'n_words': 953}