| 447 | } |
| 448 | |
| 449 | Status ConvertFromPHWC4Half(absl::Span<const HalfBits> in, const BHWC& shape, |
| 450 | absl::Span<float> out) { |
| 451 | RETURN_IF_ERROR(ValidateConvertFromPHWC4(in, shape, out)); |
| 452 | int num_planes = IntegralDivideRoundUp(shape.c, kPhwc4ChannelsInPlane); |
| 453 | const int num_pixels = shape.h * shape.w; |
| 454 | const int padded_size = num_pixels * num_planes * kPhwc4ChannelsInPlane; |
| 455 | // A layer is a set of kPhwc4ChannelsInPlane channels images. |
| 456 | const int num_full_planes = shape.c / kPhwc4ChannelsInPlane; |
| 457 | for (int b = 0; b < shape.b; b++) { |
| 458 | const HalfBits* src = in.data() + b * padded_size; |
| 459 | for (int p = 0; p < num_full_planes; p++) { |
| 460 | float* dest = |
| 461 | out.data() + shape.LinearIndex({b, 0, 0, p * kPhwc4ChannelsInPlane}); |
| 462 | for (int i = 0; i < num_pixels; i++) { |
| 463 | dest[0] = fp16_ieee_to_fp32_value(src[0]); |
| 464 | dest[1] = fp16_ieee_to_fp32_value(src[1]); |
| 465 | dest[2] = fp16_ieee_to_fp32_value(src[2]); |
| 466 | dest[3] = fp16_ieee_to_fp32_value(src[3]); |
| 467 | src += kPhwc4ChannelsInPlane; |
| 468 | dest += shape.c; |
| 469 | } |
| 470 | } |
| 471 | } |
| 472 | |
| 473 | // Unpadding last kPhwc4ChannelsInPlane-channel plane |
| 474 | const int remaining_channels = |
| 475 | shape.c - num_full_planes * kPhwc4ChannelsInPlane; |
| 476 | if (remaining_channels == 0) { |
| 477 | return OkStatus(); |
| 478 | } |
| 479 | for (int b = 0; b < shape.b; b++) { |
| 480 | const HalfBits* src = in.data() + b * padded_size + |
| 481 | num_pixels * num_full_planes * kPhwc4ChannelsInPlane; |
| 482 | float* dest = |
| 483 | out.data() + |
| 484 | shape.LinearIndex({b, 0, 0, num_full_planes * kPhwc4ChannelsInPlane}); |
| 485 | switch (remaining_channels) { |
| 486 | case 1: |
| 487 | for (int p = 0; p < num_pixels; p++) { |
| 488 | dest[0] = fp16_ieee_to_fp32_value(src[0]); |
| 489 | src += kPhwc4ChannelsInPlane; |
| 490 | dest += shape.c; |
| 491 | } |
| 492 | break; |
| 493 | case 2: |
| 494 | for (int p = 0; p < num_pixels; p++) { |
| 495 | dest[0] = fp16_ieee_to_fp32_value(src[0]); |
| 496 | dest[1] = fp16_ieee_to_fp32_value(src[1]); |
| 497 | src += kPhwc4ChannelsInPlane; |
| 498 | dest += shape.c; |
| 499 | } |
| 500 | break; |
| 501 | case 3: |
| 502 | for (int p = 0; p < num_pixels; p++) { |
| 503 | dest[0] = fp16_ieee_to_fp32_value(src[0]); |
| 504 | dest[1] = fp16_ieee_to_fp32_value(src[1]); |
| 505 | dest[2] = fp16_ieee_to_fp32_value(src[2]); |
| 506 | src += kPhwc4ChannelsInPlane; |
nothing calls this directly
no test coverage detected