-
Notifications
You must be signed in to change notification settings - Fork 398
feat(java): add float support #3254
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
46e0e29
a610788
7fc45b8
65f6ea3
6e37abb
f5ba942
ad18586
5cfb49f
2772ff2
f6f38d3
578c05e
0b98295
004663d
809ced1
65f2667
602aaed
18f899c
77178dd
343a6ce
f5ee398
b096c9b
a692296
ec14a50
91e5bbd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,158 @@ | ||
| /* | ||
| * Licensed to the Apache Software Foundation (ASF) under one | ||
| * or more contributor license agreements. See the NOTICE file | ||
| * distributed with this work for additional information | ||
| * regarding copyright ownership. The ASF licenses this file | ||
| * to you under the Apache License, Version 2.0 (the | ||
| * "License"); you may not use this file except in compliance | ||
| * with the License. You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, | ||
| * software distributed under the License is distributed on an | ||
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| * KIND, either express or implied. See the License for the | ||
| * specific language governing permissions and limitations | ||
| * under the License. | ||
| */ | ||
|
|
||
| package org.apache.fory.collection; | ||
|
|
||
| import java.util.AbstractList; | ||
| import java.util.Arrays; | ||
| import java.util.Objects; | ||
| import java.util.RandomAccess; | ||
| import org.apache.fory.type.Float16; | ||
|
|
||
| public final class Float16List extends AbstractList<Float16> implements RandomAccess { | ||
| private static final int DEFAULT_CAPACITY = 10; | ||
|
|
||
| private short[] array; | ||
| private int size; | ||
|
|
||
| public Float16List() { | ||
| this(DEFAULT_CAPACITY); | ||
| } | ||
|
|
||
| public Float16List(int initialCapacity) { | ||
| if (initialCapacity < 0) { | ||
| throw new IllegalArgumentException("Illegal capacity: " + initialCapacity); | ||
| } | ||
| this.array = new short[initialCapacity]; | ||
| this.size = 0; | ||
| } | ||
|
|
||
| public Float16List(short[] array) { | ||
| this.array = array; | ||
| this.size = array.length; | ||
| } | ||
|
|
||
| @Override | ||
| public Float16 get(int index) { | ||
| checkIndex(index); | ||
| return Float16.fromBits(array[index]); | ||
| } | ||
|
|
||
| @Override | ||
| public int size() { | ||
| return size; | ||
| } | ||
|
|
||
| @Override | ||
| public Float16 set(int index, Float16 element) { | ||
| checkIndex(index); | ||
| Objects.requireNonNull(element, "element"); | ||
| short prev = array[index]; | ||
| array[index] = element.toBits(); | ||
| return Float16.fromBits(prev); | ||
| } | ||
|
|
||
| public void set(int index, short bits) { | ||
| checkIndex(index); | ||
| array[index] = bits; | ||
| } | ||
|
|
||
| public void set(int index, float value) { | ||
| checkIndex(index); | ||
| array[index] = Float16.valueOf(value).toBits(); | ||
| } | ||
|
|
||
| @Override | ||
| public void add(int index, Float16 element) { | ||
| checkPositionIndex(index); | ||
| ensureCapacity(size + 1); | ||
| System.arraycopy(array, index, array, index + 1, size - index); | ||
| array[index] = element.toBits(); | ||
| size++; | ||
| modCount++; | ||
| } | ||
|
|
||
| @Override | ||
| public boolean add(Float16 element) { | ||
| Objects.requireNonNull(element, "element"); | ||
| ensureCapacity(size + 1); | ||
| array[size++] = element.toBits(); | ||
| modCount++; | ||
| return true; | ||
| } | ||
|
|
||
| public boolean add(short bits) { | ||
| ensureCapacity(size + 1); | ||
| array[size++] = bits; | ||
| modCount++; | ||
| return true; | ||
| } | ||
|
|
||
| public boolean add(float value) { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Float16List primitive methods still allocate Float16 objects on the hot path. add(float), set(float), and getFloat(int) all go through Float16.valueOf/fromBits, so these paths allocate even though this is a primitive-style container. A static bits conversion helper would keep these methods allocation-free. |
||
| ensureCapacity(size + 1); | ||
| array[size++] = Float16.valueOf(value).toBits(); | ||
| modCount++; | ||
| return true; | ||
| } | ||
|
|
||
| public float getFloat(int index) { | ||
| checkIndex(index); | ||
| return Float16.fromBits(array[index]).toFloat(); | ||
| } | ||
|
|
||
| public short getShort(int index) { | ||
| checkIndex(index); | ||
| return array[index]; | ||
| } | ||
|
|
||
| public boolean hasArray() { | ||
| return array != null; | ||
| } | ||
|
|
||
| public short[] getArray() { | ||
| return array; | ||
| } | ||
|
|
||
| public short[] copyArray() { | ||
| return Arrays.copyOf(array, size); | ||
| } | ||
|
|
||
| private void ensureCapacity(int minCapacity) { | ||
| if (array.length >= minCapacity) { | ||
| return; | ||
| } | ||
| int newCapacity = array.length + (array.length >> 1) + 1; | ||
| if (newCapacity < minCapacity) { | ||
| newCapacity = minCapacity; | ||
| } | ||
| array = Arrays.copyOf(array, newCapacity); | ||
| } | ||
|
|
||
| private void checkIndex(int index) { | ||
| if (index < 0 || index >= size) { | ||
| throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size); | ||
| } | ||
| } | ||
|
|
||
| private void checkPositionIndex(int index) { | ||
| if (index < 0 || index > size) { | ||
| throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size); | ||
| } | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generated equals/hashCode for float16 now use numeric semantics, but Float16.equals/hashCode are bitwise.
With this change, +0 and -0 compare equal in generated messages, and NaN is not equal to NaN, while Float16 itself uses raw-bit equality. That mismatch is surprising in user code. Can we align generated message behavior with Float16.equals/hashCode (or make the rule explicit and consistent across runtimes)?