moduleNeighbormoduleUtilsdefself.validate_dimensions(value,type,expected,adapter)dimensions=type==:sparsevec?value.dimensions:value.sizedimensions*=8iftype==:bit&&[:sqlite,:mysql].include?(adapter)ifexpected&&dimensions!=expected"Expected #{expected} dimensions, not #{dimensions}"endenddefself.validate_finite(value,type)casetypewhen:bit,:integertruewhen:sparsevecvalue.values.all?(&:finite?)elsevalue.all?(&:finite?)endenddefself.validate(value,dimensions:,type:,adapter:)if(message=validate_dimensions(value,type,dimensions,adapter))raiseError,messageendif!validate_finite(value,type)raiseError,"Values must be finite"endenddefself.normalize(value,column_info:)returnnilifvalue.nil?raiseError,"Normalize not supported for type"unless[:cube,:vector,:halfvec].include?(column_info&.type)norm=Math.sqrt(value.sum{|v|v*v})# store zero vector as all zeros# since NaN makes the distance always 0# could also throw errornorm>0?value.map{|v|v/norm}:valueenddefself.array?(value)!value.nil?&&value.respond_to?(:to_a)enddefself.adapter(model)casemodel.connection_db_config.adapterwhen/sqlite/i:sqlitewhen/mysql|trilogy/imodel.connection_pool.with_connection{|c|c.try(:mariadb?)}?:mariadb::mysqlelse:postgresqlendenddefself.type(adapter,column_type)caseadapterwhen:mysqlifcolumn_type==:binary:bitelsecolumn_typeendelsecolumn_typeendenddefself.operator(adapter,column_type,distance)caseadapterwhen:sqlitecasedistancewhen"euclidean""vec_distance_L2"when"cosine""vec_distance_cosine"when"taxicab""vec_distance_L1"when"hamming""vec_distance_hamming"endwhen:mariadbcasecolumn_typewhen:vectorcasedistancewhen"euclidean""VEC_DISTANCE_EUCLIDEAN"when"cosine""VEC_DISTANCE_COSINE"endwhen:integercasedistancewhen"hamming""BIT_COUNT"endelseraiseArgumentError,"Unsupported type: #{column_type}"endwhen:mysqlcasecolumn_typewhen:vectorcasedistancewhen"cosine""COSINE"when"euclidean""EUCLIDEAN"endwhen:binarycasedistancewhen"hamming""BIT_COUNT"endelseraiseArgumentError,"Unsupported type: #{column_type}"endelsecasecolumn_typewhen:bitcasedistancewhen"hamming""<~>"when"jaccard""<%>"when"hamming2""#"endwhen:vector,:halfvec,:sparseveccasedistancewhen"inner_product""<#>"when"cosine""<=>"when"euclidean""<->"when"taxicab""<+>"endwhen:cubecasedistancewhen"taxicab""<#>"when"chebyshev""<=>"when"euclidean","cosine""<->"endelseraiseArgumentError,"Unsupported type: #{column_type}"endendenddefself.order(adapter,type,operator,quoted_attribute,query)caseadapterwhen:sqlitecasetypewhen:int8"#{operator}(vec_int8(#{quoted_attribute}), vec_int8(#{query}))"when:bit"#{operator}(vec_bit(#{quoted_attribute}), vec_bit(#{query}))"else"#{operator}(#{quoted_attribute}, #{query})"endwhen:mariadbifoperator=="BIT_COUNT""BIT_COUNT(#{quoted_attribute} ^ #{query})"else"#{operator}(#{quoted_attribute}, #{query})"endwhen:mysqlifoperator=="BIT_COUNT""BIT_COUNT(#{quoted_attribute} ^ #{query})"elsifoperator=="COSINE""DISTANCE(#{quoted_attribute}, #{query}, 'COSINE')"else"DISTANCE(#{quoted_attribute}, #{query}, 'EUCLIDEAN')"endelseifoperator=="#""bit_count(#{quoted_attribute} # #{query})"else"#{quoted_attribute}#{operator}#{query}"endendenddefself.normalize_required?(adapter,column_type)caseadapterwhen:postgresqlcolumn_type==:cubeelsefalseendendendend