base.rb 5.48 KB
Newer Older
Brice Videau's avatar
Brice Videau committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
module CCS
  extend FFI::Library

  if ENV["LIBCCONFIGSPACE_SO"]
    ffi_lib ENV["LIBCCONFIGSPACE_SO"]
  else
    ffi_lib "cconfigspace"
  end

  class Pointer < FFI::Pointer
    def initialize(*args)
      if args.length == 2 then
        super(CCS::find_type(args[0]), args[1])
      else
        super(*args)
      end
    end
  end

  class MemoryPointer < FFI::MemoryPointer
    def initialize(size, count = 1, clear = true)
      if size.is_a?(Symbol)
        size = CCS::find_type(size)
      end
      super(size, count, clear)
    end
  end

  typedef :double, :ccs_float_t
  typedef :int64, :ccs_int_t
  typedef :int32, :ccs_bool_t
  typedef :int32, :ccs_result_t
  typedef :uint32, :ccs_hash_t

  class MemoryPointer
    alias read_ccs_float_t  read_double
    alias read_array_of_ccs_float_t  read_array_of_double
    alias read_ccs_int_t    read_int64
    alias read_array_of_ccs_int_t  read_array_of_int64
    alias read_ccs_bool_t   read_int32
    alias read_ccs_result_t read_int32
    alias read_ccs_hash_t   read_uint32
    if FFI.find_type(:size_t).size == 8
      alias read_size_t read_uint64
    else
      alias read_size_t read_uint32
    end
  end

  class Version < FFI::Struct
    layout :revision, :uint16,
           :patch,    :uint16,
           :minor,    :uint16,
           :major,    :uint16
  end
  typedef Version.by_value, :ccs_version_t

  TRUE = 1
  FALSE = 0

  typedef :pointer, :ccs_rng_t
  typedef :pointer, :ccs_distribution_t
  typedef :pointer, :ccs_hyperparameter_t
  typedef :pointer, :ccs_expression_t
  typedef :pointer, :ccs_context_t
  typedef :pointer, :ccs_configuration_space_t
  typedef :pointer, :ccs_configuration_t
  typedef :pointer, :ccs_objective_space_t
  typedef :pointer, :ccs_evaluation_t
  typedef :pointer, :ccs_tuner_t
  typedef :pointer, :ccs_object_t

  Error = enum FFI::Type::INT32, :ccs_error_t, [
    :CCS_SUCCESS,
    :CCS_INVALID_OBJECT,
    :CCS_INVALID_VALUE,
    :CCS_INVALID_TYPE,
    :CCS_INVALID_SCALE,
    :CCS_INVALID_DISTRIBUTION,
    :CCS_INVALID_HYPERPARAMETER,
    :CCS_INVALID_CONFIGURATION,
    :CCS_INVALID_NAME,
    :CCS_INVALID_CONDITION,
    :CCS_INVALID_GRAPH,
    :CCS_TYPE_NOT_COMPARABLE,
    :CCS_INVALID_BOUNDS,
    :CCS_OUT_OF_BOUNDS,
    :CCS_SAMPLING_UNSUCCESSFUL,
    :CCS_INACTIVE_HYPERPARAMETER,
    :CCS_OUT_OF_MEMORY,
    :CCS_UNSUPPORTED_OPERATION ]

  ObjectType = enum FFI::Type::INT32, :ccs_object_type_t, [
    :CCS_RNG,
    :CCS_DISTRIBUTION,
    :CCS_HYPERPARAMETER,
    :CCS_EXPRESSION,
    :CCS_CONFIGURATION_SPACE,
    :CCS_CONFIGURATION,
    :CCS_OBJECTIVE_SPACE,
    :CCS_EVALUATION,
    :CCS_TUNER ]
  class MemoryPointer
    def read_ccs_object_type_t
      ObjectType.from_native(read_int32, nil)
    end
  end

  DataType = enum FFI::Type::INT64, :ccs_data_type_t, [
    :CCS_NONE,
    :CCS_INTEGER,
    :CCS_FLOAT,
    :CCS_BOOLEAN,
    :CCS_STRING,
    :CCS_INACTIVE,
    :CCS_OBJECT ]

  NumericType = enum FFI::Type::INT64, :ccs_numeric_type_t, [
    :CCS_NUM_INTEGER, DataType.to_native(:CCS_INTEGER, nil),
    :CCS_NUM_FLOAT, DataType.to_native(:CCS_FLOAT, nil) ]
  class MemoryPointer
    def read_ccs_numeric_type_t
      NumericType.from_native(read_int32, nil)
    end
  end

  class Numeric < FFI::Union
    layout :f, :ccs_float_t,
           :i, :ccs_int_t
  end
  typedef Numeric.by_value, :ccs_numeric_t

  class Value < FFI::Union
    layout :f, :ccs_float_t,
           :i, :ccs_int_t,
           :s, :string,
           :o, :ccs_object_t
  end
  typedef Value.by_value, :ccs_value_t

  class Datum < FFI::Struct
    layout :value, :ccs_value_t,
           :type, :ccs_data_type_t
  end
  typedef Datum.by_value, :ccs_datum_t

  attach_function :ccs_init, [], :ccs_result_t
  attach_function :ccs_get_version, [], :ccs_version_t
  attach_function :ccs_retain_object, [:ccs_object_t], :ccs_result_t
  attach_function :ccs_release_object, [:ccs_object_t], :ccs_result_t
  attach_function :ccs_object_get_type, [:ccs_object_t, :pointer], :ccs_result_t
  attach_function :ccs_object_get_refcount, [:ccs_object_t, :pointer], :ccs_result_t

  class << self
    alias version ccs_get_version
  end

  def self.error_check(result)
    if result < 0
      raise StandardError, Error.from_native(-result, nil)
    end
  end

  def self.init
    res = ccs_init
    error_check(res)
    self
  end

  class Object
    class Releaser
      def initialize(handle)
        @handle = handle
      end

      def call(id)
        CCS.ccs_release_object(@handle)
      end
    end

    attr_reader :handle
    def initialize(handle, retain: false)
      @handle = handle
      if retain
        res = CCS.ccs_retain_object(handle)
        CCS.error_check(res)
      end

      ObjectSpace.define_finalizer(self, Releaser::new(handle))
    end

    def object_type
      ptr = MemoryPointer::new(:ccs_object_type_t)
      res = CCS.ccs_object_get_type(@handle, ptr)
      CCS.error_check(res)
      return ptr.read_ccs_object_type_t
    end

    def refcount
      ptr = MemoryPointer::new(:int32)
      res = CCS.ccs_object_get_refcount(@handle, ptr)
      CCS.error_check(res)
      return ptr.read_int32
    end

    def to_ptr
      @handle
    end

    def self.add_property(name, type, accessor, memoize: false)
      src = ""
      src << "def #{name}\n"
      src << "  @#{name} ||= begin\n" if memoize
      src << "  ptr = MemoryPointer::new(:#{type})\n"
      src << "  res = CCS.#{accessor}(@handle, ptr)\n"
      src << "  CCS.error_check(res)\n"
      src << "  ptr.read_#{type}\n"
      src << "  end\n" if memoize
      src << "end\n"
      class_eval src
    end
  end

end