grnexus 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,130 @@
1
+ require 'ffi'
2
+ require 'rbconfig'
3
+
4
+ module GRNEXUSCore
5
+ extend FFI::Library
6
+
7
+ # Detect operating system and load appropriate library
8
+ def self.detect_library
9
+ script_dir = File.dirname(File.expand_path(__FILE__))
10
+ os = RbConfig::CONFIG['host_os']
11
+
12
+ case os
13
+ when /mswin|mingw|cygwin/
14
+ File.join(script_dir, '..', 'exports', 'Windows', 'grnexus_core.dll')
15
+ when /darwin/
16
+ File.join(script_dir, '..', 'exports', 'Mac', 'grnexus_core.dylib')
17
+ when /linux/
18
+ File.join(script_dir, '..', 'exports', 'Linux', 'grnexus_core.so')
19
+ else
20
+ raise "Sistema operativo no soportado: #{os}"
21
+ end
22
+ end
23
+
24
+ # Load library
25
+ ffi_lib detect_library
26
+
27
+ # Define GRNexusData structure
28
+ class GRNexusData < FFI::Struct
29
+ layout :data, :pointer,
30
+ :type, :int,
31
+ :size, :size_t,
32
+ :stride, :size_t,
33
+ :dims, [:size_t, 3]
34
+ end
35
+
36
+ # Attach C functions
37
+ attach_function :matrix_multiply, [GRNexusData.ptr, GRNexusData.ptr, GRNexusData.ptr], :int
38
+ attach_function :matrix_add, [GRNexusData.ptr, GRNexusData.ptr, GRNexusData.ptr], :int
39
+ attach_function :matrix_transpose, [GRNexusData.ptr, GRNexusData.ptr], :int
40
+ attach_function :matrix_hadamard, [GRNexusData.ptr, GRNexusData.ptr, GRNexusData.ptr], :int
41
+ attach_function :matrix_scale, [GRNexusData.ptr, :double, GRNexusData.ptr], :int
42
+
43
+ attach_function :dense_forward, [GRNexusData.ptr, GRNexusData.ptr, GRNexusData.ptr, GRNexusData.ptr], :int
44
+ attach_function :dense_backward, [GRNexusData.ptr, GRNexusData.ptr, GRNexusData.ptr, GRNexusData.ptr, GRNexusData.ptr, GRNexusData.ptr, :double], :int
45
+
46
+ attach_function :cross_entropy_loss, [GRNexusData.ptr, GRNexusData.ptr], :double
47
+ attach_function :cross_entropy_gradient, [GRNexusData.ptr, GRNexusData.ptr, GRNexusData.ptr], :int
48
+ attach_function :mse_loss, [GRNexusData.ptr, GRNexusData.ptr], :double
49
+ attach_function :mse_gradient, [GRNexusData.ptr, GRNexusData.ptr, GRNexusData.ptr], :int
50
+
51
+ attach_function :sgd_update, [GRNexusData.ptr, GRNexusData.ptr, :double], :int
52
+ attach_function :adam_update, [GRNexusData.ptr, GRNexusData.ptr, GRNexusData.ptr, GRNexusData.ptr, :double, :double, :double, :double, :int], :int
53
+ attach_function :rmsprop_update, [GRNexusData.ptr, GRNexusData.ptr, GRNexusData.ptr, :double, :double, :double], :int
54
+
55
+ attach_function :xavier_init, [GRNexusData.ptr, :size_t, :size_t], :int
56
+ attach_function :he_init, [GRNexusData.ptr, :size_t], :int
57
+ attach_function :clip_gradients, [GRNexusData.ptr, :double], :int
58
+
59
+ # Helper methods to create GRNexusData structures
60
+ def self.create_matrix_data(matrix)
61
+ rows = matrix.length
62
+ cols = matrix[0].length
63
+ size = rows * cols
64
+
65
+ buffer = FFI::MemoryPointer.new(:double, size)
66
+ flat_data = matrix.flatten
67
+ buffer.write_array_of_double(flat_data)
68
+
69
+ data_ptr = FFI::MemoryPointer.new(GRNexusData.size)
70
+ struct_instance = GRNexusData.new(data_ptr)
71
+ struct_instance[:data] = buffer
72
+ struct_instance[:type] = 3 # MATRIX
73
+ struct_instance[:size] = size
74
+ struct_instance[:stride] = cols
75
+ struct_instance[:dims][0] = rows
76
+ struct_instance[:dims][1] = cols
77
+ struct_instance[:dims][2] = 0
78
+
79
+ [data_ptr, buffer]
80
+ end
81
+
82
+ def self.create_vector_data(vector)
83
+ size = vector.length
84
+
85
+ buffer = FFI::MemoryPointer.new(:double, size)
86
+ buffer.write_array_of_double(vector)
87
+
88
+ data_ptr = FFI::MemoryPointer.new(GRNexusData.size)
89
+ struct_instance = GRNexusData.new(data_ptr)
90
+ struct_instance[:data] = buffer
91
+ struct_instance[:type] = 2 # VECTOR
92
+ struct_instance[:size] = size
93
+ struct_instance[:stride] = 1
94
+ struct_instance[:dims][0] = size
95
+ struct_instance[:dims][1] = 0
96
+ struct_instance[:dims][2] = 0
97
+
98
+ [data_ptr, buffer]
99
+ end
100
+
101
+ def self.create_output_matrix_data(rows, cols)
102
+ size = rows * cols
103
+ buffer = FFI::MemoryPointer.new(:double, size)
104
+
105
+ data_ptr = FFI::MemoryPointer.new(GRNexusData.size)
106
+ struct_instance = GRNexusData.new(data_ptr)
107
+ struct_instance[:data] = buffer
108
+ struct_instance[:type] = 3 # MATRIX
109
+ struct_instance[:size] = size
110
+ struct_instance[:stride] = cols
111
+ struct_instance[:dims][0] = rows
112
+ struct_instance[:dims][1] = cols
113
+ struct_instance[:dims][2] = 0
114
+
115
+ [data_ptr, buffer]
116
+ end
117
+
118
+ def self.read_matrix_data(buffer, rows, cols)
119
+ data = buffer.read_array_of_double(rows * cols)
120
+ matrix = []
121
+ rows.times do |i|
122
+ matrix << data[i * cols, cols]
123
+ end
124
+ matrix
125
+ end
126
+
127
+ def self.read_vector_data(buffer, size)
128
+ buffer.read_array_of_double(size)
129
+ end
130
+ end