This is an automated email from the ASF dual-hosted git repository.

chaokunyang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/fory.git


The following commit(s) were added to refs/heads/main by this push:
     new 97edbfb80 feat(javascript): add bfloat16 and bfloat16_array support 
(#3328)
97edbfb80 is described below

commit 97edbfb80bc8dede1bedc8bda20a84a54d997161
Author: Talha Amjad <[email protected]>
AuthorDate: Fri Feb 13 07:52:22 2026 +0500

    feat(javascript): add bfloat16 and bfloat16_array support (#3328)
    
    ## Summary
    
    Adds **bfloat16** and **bfloat16_array** support to the Fory JavaScript
    runtime and codegen, following the same structure as the existing
    float16 implementation.
    
    Fixes #3288
    
    ## Changes
    
    ### Runtime
    - **BFloat16** class with `fromBits()` / `toBits()` and `fromFloat32()`
    / `toFloat32()` (IEEE 754 compliant, round-to-nearest ties-to-even for
    float32→bfloat16).
    - **BFloat16Array** backed by `Uint16Array` for packed bfloat16 arrays;
    supports iteration and `fromRaw()` for deserialization.
    - Wire format: 2 bytes per value (little-endian), matching existing
    float32/float64 behavior. NaN/Inf/±0/subnormals round-trip correctly.
    
    ### Type system & serialization
    - `Type.bfloat16()` and `Type.bfloat16Array()`.
    - Serializers registered in type resolver; reader returns `BFloat16` (no
    raw uint16 in public API).
    - Codegen: `gen/builder.ts`, `gen/number.ts`, and `gen/typedArray.ts`
    updated for bfloat16 and bfloat16_array.
    
    ### API
    - `BFloat16` and `BFloat16Array` exported from the package.
    - Writer accepts `BFloat16 | number` for scalar bfloat16; arrays accept
    `BFloat16[]` or `BFloat16Array`.
    
    ### Tests
    - Scalar: normal values, NaN, Infinity, ±0 round-trip.
    - Array: `bfloat16Array` with number array and with `BFloat16Array`.
    
    ## Checklist
    - [x] BFloat16 type with to_bits/from_bits and float32 conversions
    - [x] BFloat16Array with packed Uint16Array storage
    - [x] Wire format 2 bytes, endianness aligned with float32/float64
    - [x] Type.bfloat16() and Type.bfloat16Array(); resolver and codegen
    - [x] Tests for scalar and array serialization/round-trip
---
 javascript/packages/fory/index.ts              |   3 +
 javascript/packages/fory/lib/bfloat16.ts       | 121 +++++++++++++++++++++++++
 javascript/packages/fory/lib/gen/builder.ts    |   8 ++
 javascript/packages/fory/lib/gen/number.ts     |   6 ++
 javascript/packages/fory/lib/gen/typedArray.ts |  41 +++++++++
 javascript/packages/fory/lib/reader/index.ts   |   5 +
 javascript/packages/fory/lib/typeInfo.ts       |  19 +++-
 javascript/packages/fory/lib/typeResolver.ts   |   2 +
 javascript/packages/fory/lib/writer/index.ts   |   9 +-
 javascript/packages/fory/lib/writer/number.ts  |  22 +++++
 javascript/test/array.test.ts                  |  37 +++++++-
 javascript/test/number.test.ts                 |  70 +++++++++++++-
 12 files changed, 338 insertions(+), 5 deletions(-)

diff --git a/javascript/packages/fory/index.ts 
b/javascript/packages/fory/index.ts
index 36c73ac82..efb460796 100644
--- a/javascript/packages/fory/index.ts
+++ b/javascript/packages/fory/index.ts
@@ -29,6 +29,7 @@ import { Serializer, Mode } from "./lib/type";
 import Fory from "./lib/fory";
 import { BinaryReader } from "./lib/reader";
 import { BinaryWriter } from "./lib/writer";
+import { BFloat16, BFloat16Array } from "./lib/bfloat16";
 
 export {
   Serializer,
@@ -41,6 +42,8 @@ export {
   ForyField,
   Dynamic,
   BinaryReader,
+  BFloat16,
+  BFloat16Array,
 };
 
 export default Fory;
diff --git a/javascript/packages/fory/lib/bfloat16.ts 
b/javascript/packages/fory/lib/bfloat16.ts
new file mode 100644
index 000000000..0beb46d44
--- /dev/null
+++ b/javascript/packages/fory/lib/bfloat16.ts
@@ -0,0 +1,121 @@
+/*
+ * 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.
+ */
+
+const float32View = new Float32Array(1);
+const uint32View = new Uint32Array(float32View.buffer);
+
+export class BFloat16 {
+  private readonly _bits: number;
+
+  constructor(bits: number) {
+    this._bits = bits & 0xffff;
+  }
+
+  toBits(): number {
+    return this._bits;
+  }
+
+  static fromBits(bits: number): BFloat16 {
+    return new BFloat16(bits & 0xffff);
+  }
+
+  static fromFloat32(f32: number): BFloat16 {
+    float32View[0] = f32;
+    const bits = uint32View[0];
+    const exponent = (bits >> 23) & 0xff;
+    if (exponent === 255) {
+      return BFloat16.fromBits((bits >> 16) & 0xffff);
+    }
+    const remainder = bits & 0x1ffff;
+    let u = (bits + 0x8000) >> 16;
+    if (remainder === 0x8000 && (u & 1) !== 0) {
+      u--;
+    }
+    return BFloat16.fromBits(u & 0xffff);
+  }
+
+  toFloat32(): number {
+    float32View[0] = 0;
+    uint32View[0] = this._bits << 16;
+    return float32View[0];
+  }
+}
+
+export class BFloat16Array {
+  private readonly _data: Uint16Array;
+
+  constructor(length: number);
+  constructor(source: Uint16Array | BFloat16[] | number[]);
+  constructor(lengthOrSource: number | Uint16Array | BFloat16[] | number[]) {
+    if (typeof lengthOrSource === "number") {
+      this._data = new Uint16Array(lengthOrSource);
+    } else if (lengthOrSource instanceof Uint16Array) {
+      this._data = new Uint16Array(lengthOrSource.length);
+      this._data.set(lengthOrSource);
+    } else {
+      const arr = lengthOrSource as (BFloat16 | number)[];
+      this._data = new Uint16Array(arr.length);
+      for (let i = 0; i < arr.length; i++) {
+        const v = arr[i];
+        this._data[i]
+          = v instanceof BFloat16 ? v.toBits() : 
BFloat16.fromFloat32(v).toBits();
+      }
+    }
+  }
+
+  get length(): number {
+    return this._data.length;
+  }
+
+  get(index: number): BFloat16 {
+    return BFloat16.fromBits(this._data[index]);
+  }
+
+  set(index: number, value: BFloat16 | number): void {
+    this._data[index]
+      = value instanceof BFloat16 ? value.toBits() : 
BFloat16.fromFloat32(value).toBits();
+  }
+
+  get raw(): Uint16Array {
+    return this._data;
+  }
+
+  static fromRaw(data: Uint16Array): BFloat16Array {
+    const arr = new BFloat16Array(data.length);
+    arr._data.set(data);
+    return arr;
+  }
+
+  [Symbol.iterator](): IterableIterator<BFloat16> {
+    let i = 0;
+    const data = this._data;
+    const len = data.length;
+    return {
+      next(): IteratorResult<BFloat16> {
+        if (i < len) {
+          return { value: BFloat16.fromBits(data[i++]), done: false };
+        }
+        return { value: undefined as unknown as BFloat16, done: true };
+      },
+      [Symbol.iterator]() {
+        return this;
+      },
+    };
+  }
+}
diff --git a/javascript/packages/fory/lib/gen/builder.ts 
b/javascript/packages/fory/lib/gen/builder.ts
index 7627340d1..e8610c0fe 100644
--- a/javascript/packages/fory/lib/gen/builder.ts
+++ b/javascript/packages/fory/lib/gen/builder.ts
@@ -115,6 +115,10 @@ export class BinaryReaderBuilder {
     return `${this.holder}.float16()`;
   }
 
+  bfloat16() {
+    return `${this.holder}.bfloat16()`;
+  }
+
   uint16() {
     return `${this.holder}.uint16()`;
   }
@@ -257,6 +261,10 @@ class BinaryWriterBuilder {
     return `${this.holder}.float16(${v})`;
   }
 
+  bfloat16(v: number | string) {
+    return `${this.holder}.bfloat16(${v})`;
+  }
+
   int64(v: number | string) {
     return `${this.holder}.int64(${v})`;
   }
diff --git a/javascript/packages/fory/lib/gen/number.ts 
b/javascript/packages/fory/lib/gen/number.ts
index dd3380d5a..0eef57bae 100644
--- a/javascript/packages/fory/lib/gen/number.ts
+++ b/javascript/packages/fory/lib/gen/number.ts
@@ -102,6 +102,12 @@ CodegenRegistry.register(TypeId.FLOAT16,
     builder => builder.reader.float16()
   )
 );
+CodegenRegistry.register(TypeId.BFLOAT16,
+  buildNumberSerializer(
+    (builder, accessor) => builder.writer.bfloat16(accessor),
+    builder => builder.reader.bfloat16()
+  )
+);
 CodegenRegistry.register(TypeId.FLOAT32,
   buildNumberSerializer(
     (builder, accessor) => builder.writer.float32(accessor),
diff --git a/javascript/packages/fory/lib/gen/typedArray.ts 
b/javascript/packages/fory/lib/gen/typedArray.ts
index 38659a4d7..4330443fa 100644
--- a/javascript/packages/fory/lib/gen/typedArray.ts
+++ b/javascript/packages/fory/lib/gen/typedArray.ts
@@ -137,6 +137,46 @@ class Float16ArraySerializerGenerator extends 
BaseSerializerGenerator {
     return 7;
   }
 }
+
+class BFloat16ArraySerializerGenerator extends BaseSerializerGenerator {
+  typeInfo: TypeInfo;
+
+  constructor(typeInfo: TypeInfo, builder: CodecBuilder, scope: Scope) {
+    super(typeInfo, builder, scope);
+    this.typeInfo = <TypeInfo>typeInfo;
+  }
+
+  write(accessor: string): string {
+    const item = this.scope.uniqueName("item");
+    return `
+        ${this.builder.writer.varUInt32(`${accessor}.length * 2`)}
+        ${this.builder.writer.reserve(`${accessor}.length * 2`)};
+        for (const ${item} of ${accessor}) {
+          ${this.builder.writer.bfloat16(item)}
+        }
+    `;
+  }
+
+  read(accessor: (expr: string) => string, refState: string): string {
+    const result = this.scope.uniqueName("result");
+    const len = this.scope.uniqueName("len");
+    const idx = this.scope.uniqueName("idx");
+    return `
+        const ${len} = ${this.builder.reader.varUInt32()} / 2;
+        const ${result} = new Array(${len});
+        ${this.maybeReference(result, refState)}
+        for (let ${idx} = 0; ${idx} < ${len}; ${idx}++) {
+          ${result}[${idx}] = ${this.builder.reader.bfloat16()};
+        }
+        ${accessor(result)}
+      `;
+  }
+
+  getFixedSize(): number {
+    return 7;
+  }
+}
+
 CodegenRegistry.register(TypeId.BOOL_ARRAY, BoolArraySerializerGenerator);
 CodegenRegistry.register(TypeId.BINARY, build(Type.uint8(), `Uint8Array`, 1));
 CodegenRegistry.register(TypeId.INT8_ARRAY, build(Type.int8(), `Int8Array`, 
1));
@@ -148,5 +188,6 @@ CodegenRegistry.register(TypeId.UINT16_ARRAY, 
build(Type.uint16(), `Uint16Array`
 CodegenRegistry.register(TypeId.UINT32_ARRAY, build(Type.uint32(), 
`Uint32Array`, 4));
 CodegenRegistry.register(TypeId.UINT64_ARRAY, build(Type.uint64(), 
`BigUint64Array`, 8));
 CodegenRegistry.register(TypeId.FLOAT16_ARRAY, 
Float16ArraySerializerGenerator);
+CodegenRegistry.register(TypeId.BFLOAT16_ARRAY, 
BFloat16ArraySerializerGenerator);
 CodegenRegistry.register(TypeId.FLOAT32_ARRAY, build(Type.float32(), 
`Float32Array`, 4));
 CodegenRegistry.register(TypeId.FLOAT64_ARRAY, build(Type.float64(), 
`Float64Array`, 6));
diff --git a/javascript/packages/fory/lib/reader/index.ts 
b/javascript/packages/fory/lib/reader/index.ts
index d63cd2f15..9786b0bf2 100644
--- a/javascript/packages/fory/lib/reader/index.ts
+++ b/javascript/packages/fory/lib/reader/index.ts
@@ -21,6 +21,7 @@ import { LATIN1, UTF16, UTF8 } from "../type";
 import { isNodeEnv } from "../util";
 import { PlatformBuffer, alloc, fromUint8Array } from "../platformBuffer";
 import { readLatin1String } from "./string";
+import { BFloat16 } from "../bfloat16";
 
 export class BinaryReader {
   private sliceStringEnable;
@@ -508,6 +509,10 @@ export class BinaryReader {
     }
   }
 
+  bfloat16(): BFloat16 {
+    return BFloat16.fromBits(this.uint16());
+  }
+
   getCursor() {
     return this.cursor;
   }
diff --git a/javascript/packages/fory/lib/typeInfo.ts 
b/javascript/packages/fory/lib/typeInfo.ts
index 9359eb7ae..cfa6e69fb 100644
--- a/javascript/packages/fory/lib/typeInfo.ts
+++ b/javascript/packages/fory/lib/typeInfo.ts
@@ -19,6 +19,7 @@
 
 import Fory from "./fory";
 import { ForyTypeInfoSymbol, TypeId, Mode } from "./type";
+import { BFloat16 } from "./bfloat16";
 
 const targetFieldInfo = new WeakMap<new () => any, { [key: string]: 
StructFieldInfo }>();
 
@@ -465,6 +466,8 @@ export type HintInput<T> = T extends {
     type: typeof TypeId.STRING;
   }
   ? string
+  : T extends { type: typeof TypeId.BFLOAT16 }
+  ? BFloat16 | number
   : T extends {
     type:
     | typeof TypeId["INT8"]
@@ -479,7 +482,6 @@ export type HintInput<T> = T extends {
     | typeof TypeId.VAR_UINT32
     | typeof TypeId.FLOAT8
     | typeof TypeId.FLOAT16
-    | typeof TypeId.BFLOAT16
     | typeof TypeId.FLOAT32
     | typeof TypeId.FLOAT64;
   }
@@ -537,6 +539,8 @@ export type HintResult<T> = T extends never ? any : T 
extends {
     type: typeof TypeId.STRING;
   }
   ? string
+  : T extends { type: typeof TypeId.BFLOAT16 }
+  ? BFloat16
   : T extends {
     type:
     | typeof TypeId.INT8
@@ -549,7 +553,6 @@ export type HintResult<T> = T extends never ? any : T 
extends {
     | typeof TypeId.VAR_UINT32
     | typeof TypeId.FLOAT8
     | typeof TypeId.FLOAT16
-    | typeof TypeId.BFLOAT16
     | typeof TypeId.FLOAT32
     | typeof TypeId.FLOAT64;
   }
@@ -729,6 +732,12 @@ export const Type = {
 
     );
   },
+  bfloat16() {
+    return TypeInfo.fromNonParam<typeof TypeId.BFLOAT16>(
+      (TypeId.BFLOAT16),
+
+    );
+  },
   float32() {
     return TypeInfo.fromNonParam<typeof TypeId.FLOAT32>(
       (TypeId.FLOAT32),
@@ -862,6 +871,12 @@ export const Type = {
 
     );
   },
+  bfloat16Array() {
+    return TypeInfo.fromNonParam<typeof TypeId.BFLOAT16_ARRAY>(
+      (TypeId.BFLOAT16_ARRAY),
+
+    );
+  },
   float32Array() {
     return TypeInfo.fromNonParam<typeof TypeId.FLOAT32_ARRAY>(
       (TypeId.FLOAT32_ARRAY),
diff --git a/javascript/packages/fory/lib/typeResolver.ts 
b/javascript/packages/fory/lib/typeResolver.ts
index e11de059a..a06c9e7f8 100644
--- a/javascript/packages/fory/lib/typeResolver.ts
+++ b/javascript/packages/fory/lib/typeResolver.ts
@@ -110,6 +110,7 @@ export default class TypeResolver {
     registerSerializer(Type.taggedUInt64());
     registerSerializer(Type.sliInt64());
     registerSerializer(Type.float16());
+    registerSerializer(Type.bfloat16());
     registerSerializer(Type.float32());
     registerSerializer(Type.float64());
     registerSerializer(Type.timestamp());
@@ -127,6 +128,7 @@ export default class TypeResolver {
     registerSerializer(Type.uint64Array());
     registerSerializer(Type.int64Array());
     registerSerializer(Type.float16Array());
+    registerSerializer(Type.bfloat16Array());
     registerSerializer(Type.float32Array());
     registerSerializer(Type.float64Array());
 
diff --git a/javascript/packages/fory/lib/writer/index.ts 
b/javascript/packages/fory/lib/writer/index.ts
index bbb28a419..2d7992c47 100644
--- a/javascript/packages/fory/lib/writer/index.ts
+++ b/javascript/packages/fory/lib/writer/index.ts
@@ -20,7 +20,8 @@
 import { HalfMaxInt32, HalfMinInt32, Hps, LATIN1, UTF16, UTF8 } from "../type";
 import { PlatformBuffer, alloc, strByteLength } from "../platformBuffer";
 import { OwnershipError } from "../error";
-import { toFloat16 } from "./number";
+import { toFloat16, toBFloat16 } from "./number";
+import { BFloat16 } from "../bfloat16";
 
 const MAX_POOL_SIZE = 1024 * 1024 * 3; // 3MB
 
@@ -455,6 +456,12 @@ export class BinaryWriter {
     this.uint16(toFloat16(value));
   }
 
+  bfloat16(value: BFloat16 | number) {
+    const bits
+      = value instanceof BFloat16 ? value.toBits() : toBFloat16(value);
+    this.uint16(bits);
+  }
+
   getCursor() {
     return this.cursor;
   }
diff --git a/javascript/packages/fory/lib/writer/number.ts 
b/javascript/packages/fory/lib/writer/number.ts
index 8729dc372..1c38ce39e 100644
--- a/javascript/packages/fory/lib/writer/number.ts
+++ b/javascript/packages/fory/lib/writer/number.ts
@@ -43,3 +43,25 @@ export function toFloat16(value: number) {
 
   return sign | ((exponent + 15) << 10) | (significand >> 13);
 }
+
+const float32ViewBf = new Float32Array(1);
+const uint32ViewBf = new Uint32Array(float32ViewBf.buffer);
+
+/**
+ * Convert float32 to bfloat16 bits (round-to-nearest, ties-to-even).
+ * BFloat16 layout: 1 sign, 8 exponent, 7 mantissa.
+ */
+export function toBFloat16(value: number): number {
+  float32ViewBf[0] = value;
+  const bits = uint32ViewBf[0];
+  const exponent = (bits >> 23) & 0xff;
+  if (exponent === 255) {
+    return (bits >> 16) & 0xffff;
+  }
+  const remainder = bits & 0x1ffff;
+  let u = (bits + 0x8000) >> 16;
+  if (remainder === 0x8000 && (u & 1) !== 0) {
+    u--;
+  }
+  return u & 0xffff;
+}
diff --git a/javascript/test/array.test.ts b/javascript/test/array.test.ts
index c8c094858..0abbd571a 100644
--- a/javascript/test/array.test.ts
+++ b/javascript/test/array.test.ts
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-import Fory, { Type } from '../packages/fory/index';
+import Fory, { Type, BFloat16Array } from '../packages/fory/index';
 import { describe, expect, test } from '@jest/globals';
 import * as beautify from 'js-beautify';
 
@@ -113,6 +113,41 @@ describe('array', () => {
     expect(result.a6[1]).toBeCloseTo(2.5, 1)
     expect(result.a6[2]).toBeCloseTo(-4.5, 1)
   });
+
+  test('should bfloat16Array work', () => {
+    const typeinfo = Type.struct({
+      typeName: "example.foo"
+    }, {
+      a7: Type.bfloat16Array(),
+    });
+    const fory = new Fory({ refTracking: true });
+    const serialize = fory.registerSerializer(typeinfo).serializer;
+    const input = fory.serialize({
+      a7: [1.5, 2.5, -4.5],
+    }, serialize);
+    const result = fory.deserialize(input);
+    expect(result.a7).toHaveLength(3);
+    expect(result.a7[0].toFloat32()).toBeCloseTo(1.5, 2);
+    expect(result.a7[1].toFloat32()).toBeCloseTo(2.5, 2);
+    expect(result.a7[2].toFloat32()).toBeCloseTo(-4.5, 2);
+  });
+
+  test('should bfloat16Array accept BFloat16Array', () => {
+    const typeinfo = Type.struct({
+      typeName: "example.foo"
+    }, {
+      a7: Type.bfloat16Array(),
+    });
+    const fory = new Fory({ refTracking: true });
+    const serialize = fory.registerSerializer(typeinfo).serializer;
+    const arr = new BFloat16Array([1.25, -2.5, 0]);
+    const input = fory.serialize({ a7: arr }, serialize);
+    const result = fory.deserialize(input);
+    expect(result.a7).toHaveLength(3);
+    expect(result.a7[0].toFloat32()).toBeCloseTo(1.25, 2);
+    expect(result.a7[1].toFloat32()).toBeCloseTo(-2.5, 2);
+    expect(result.a7[2].toFloat32()).toBe(0);
+  });
 });
 
 
diff --git a/javascript/test/number.test.ts b/javascript/test/number.test.ts
index a13185be9..3201905ce 100644
--- a/javascript/test/number.test.ts
+++ b/javascript/test/number.test.ts
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-import Fory, { Type } from '../packages/fory/index';
+import Fory, { Type, BFloat16 } from '../packages/fory/index';
 import { describe, expect, test } from '@jest/globals';
 
 describe('number', () => {
@@ -153,6 +153,74 @@ describe('number', () => {
     expect(result.a).toBeCloseTo(Infinity)
   });
 
+  test('should bfloat16 work', () => {
+    const fory = new Fory({ refTracking: true });
+    const serializer = fory.registerSerializer(Type.struct({
+      typeName: "example.foo"
+    }, {
+      a: Type.bfloat16()
+    })).serializer;
+    const input = fory.serialize({ a: BFloat16.fromFloat32(1.5) }, serializer);
+    const result = fory.deserialize(input);
+    expect(result.a).toBeInstanceOf(BFloat16);
+    expect(result.a.toFloat32()).toBeCloseTo(1.5, 2);
+  });
+
+  test('should bfloat16 accept number', () => {
+    const fory = new Fory({ refTracking: true });
+    const serializer = fory.registerSerializer(Type.struct({
+      typeName: "example.foo"
+    }, {
+      a: Type.bfloat16()
+    })).serializer;
+    const input = fory.serialize({ a: 1.5 }, serializer);
+    const result = fory.deserialize(input);
+    expect(result.a).toBeInstanceOf(BFloat16);
+    expect(result.a.toFloat32()).toBeCloseTo(1.5, 2);
+  });
+
+  test('should bfloat16 NaN work', () => {
+    const fory = new Fory({ refTracking: true });
+    const serializer = fory.registerSerializer(Type.struct({
+      typeName: "example.foo"
+    }, {
+      a: Type.bfloat16()
+    })).serializer;
+    const input = fory.serialize({ a: NaN }, serializer);
+    const result = fory.deserialize(input);
+    expect(result.a).toBeInstanceOf(BFloat16);
+    expect(Number.isNaN(result.a.toFloat32())).toBe(true);
+  });
+
+  test('should bfloat16 Infinity work', () => {
+    const fory = new Fory({ refTracking: true });
+    const serializer = fory.registerSerializer(Type.struct({
+      typeName: "example.foo"
+    }, {
+      a: Type.bfloat16()
+    })).serializer;
+    const input = fory.serialize({ a: Infinity }, serializer);
+    const result = fory.deserialize(input);
+    expect(result.a).toBeInstanceOf(BFloat16);
+    expect(result.a.toFloat32()).toBe(Infinity);
+  });
+
+  test('should bfloat16 zero and neg zero round-trip', () => {
+    const fory = new Fory({ refTracking: true });
+    const serializer = fory.registerSerializer(Type.struct({
+      typeName: "example.foo"
+    }, {
+      a: Type.bfloat16(),
+      b: Type.bfloat16()
+    })).serializer;
+    const input = fory.serialize({ a: 0, b: -0 }, serializer);
+    const result = fory.deserialize(input);
+    expect(result.a.toFloat32()).toBe(0);
+    expect(result.b.toFloat32()).toBe(-0);
+    expect(1 / result.a.toFloat32()).toBe(Infinity);
+    expect(1 / result.b.toFloat32()).toBe(-Infinity);
+  });
+
   test('should uint8 work', () => {
     const fory = new Fory({ refTracking: true });
     const serializer = fory.registerSerializer(Type.struct({


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to