| 67 | } |
| 68 | |
| 69 | void Compute(OpKernelContext* context) override { |
| 70 | const Tensor& input = context->input(0); |
| 71 | |
| 72 | if (input.NumElements() <= 1 || input.dim_size(0) <= 1) { |
| 73 | // No shuffling is required, so copy input directly to output |
| 74 | context->set_output(0, input); |
| 75 | } else { |
| 76 | // Reserve enough random samples for shuffling |
| 77 | const int64 size = input.dim_size(0); |
| 78 | const int64 samples = size - 1; |
| 79 | auto local_gen = generator_.ReserveSamples32(samples); |
| 80 | random::SingleSampleAdapter<random::PhiloxRandom> single(&local_gen); |
| 81 | const auto uniform = [&single](uint32 n) { return single() % n; }; |
| 82 | |
| 83 | if (input.dims() == 1) { |
| 84 | // For 1D data, copy and then shuffle in place |
| 85 | context->set_output(0, tensor::DeepCopy(input)); |
| 86 | auto vec = context->mutable_output(0)->vec<T>(); |
| 87 | RandomShuffle(vec.data(), vec.data() + size, uniform); |
| 88 | } else { |
| 89 | // For >= 2D, shuffle indices and then copy across |
| 90 | Tensor* output = nullptr; |
| 91 | OP_REQUIRES_OK(context, |
| 92 | context->allocate_output(0, input.shape(), &output)); |
| 93 | const auto input_mat = input.flat_outer_dims<T>(); |
| 94 | auto output_mat = output->flat_outer_dims<T>(); |
| 95 | if (size < kint32max) { |
| 96 | IndexedShuffle<int32>(size, input_mat, output_mat, uniform); |
| 97 | } else { |
| 98 | IndexedShuffle<int64>(size, input_mat, output_mat, uniform); |
| 99 | } |
| 100 | } |
| 101 | } |
| 102 | } |
| 103 | |
| 104 | private: |
| 105 | GuardedPhiloxRandom generator_; |
nothing calls this directly
no test coverage detected