Mercurial > hgrepos > Python2 > PyMuPDF
diff mupdf-source/thirdparty/tesseract/src/lstm/networkscratch.h @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mupdf-source/thirdparty/tesseract/src/lstm/networkscratch.h Mon Sep 15 11:43:07 2025 +0200 @@ -0,0 +1,279 @@ +/////////////////////////////////////////////////////////////////////// +// File: networkscratch.h +// Description: Scratch space for Network layers that hides distinction +// between float/int implementations. +// Author: Ray Smith +// +// (C) Copyright 2014, Google Inc. +// Licensed 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. +/////////////////////////////////////////////////////////////////////// + +#ifndef TESSERACT_LSTM_NETWORKSCRATCH_H_ +#define TESSERACT_LSTM_NETWORKSCRATCH_H_ + +#include <mutex> +#include "matrix.h" +#include "networkio.h" + +namespace tesseract { + +// Generic scratch space for network layers. Provides NetworkIO that can store +// a complete set (over time) of intermediates, and vector<float> +// scratch space that auto-frees after use. The aim here is to provide a set +// of temporary buffers to network layers that can be reused between layers +// and don't have to be reallocated on each call. +class NetworkScratch { +public: + NetworkScratch() : int_mode_(false) {} + ~NetworkScratch() = default; + + // Sets the network representation. If the representation is integer, then + // default (integer) NetworkIOs are separated from the always-float variety. + // This saves memory by having separate int-specific and float-specific + // stacks. If the network representation is float, then all NetworkIOs go + // to the float stack. + void set_int_mode(bool int_mode) { + int_mode_ = int_mode; + } + + // Class that acts like a NetworkIO (by having an implicit cast operator), + // yet actually holds a pointer to NetworkIOs in the source NetworkScratch, + // and knows how to unstack the borrowed pointers on destruction. + class IO { + public: + // The NetworkIO should be sized after construction. + IO(const NetworkIO &src, NetworkScratch *scratch) + : int_mode_(scratch->int_mode_ && src.int_mode()), scratch_space_(scratch) { + network_io_ = + int_mode_ ? scratch_space_->int_stack_.Borrow() : scratch_space_->float_stack_.Borrow(); + } + // Default constructor for arrays. Use one of the Resize functions + // below to initialize and size. + IO() : int_mode_(false), network_io_(nullptr), scratch_space_(nullptr) {} + + ~IO() { + if (scratch_space_ == nullptr) { + ASSERT_HOST(network_io_ == nullptr); + } else if (int_mode_) { + scratch_space_->int_stack_.Return(network_io_); + } else { + scratch_space_->float_stack_.Return(network_io_); + } + } + // Resizes the array (and stride), avoiding realloc if possible, to the + // size from various size specs: + // Same time size, given number of features. + void Resize(const NetworkIO &src, int num_features, NetworkScratch *scratch) { + if (scratch_space_ == nullptr) { + int_mode_ = scratch->int_mode_ && src.int_mode(); + scratch_space_ = scratch; + network_io_ = + int_mode_ ? scratch_space_->int_stack_.Borrow() : scratch_space_->float_stack_.Borrow(); + } + network_io_->Resize(src, num_features); + } + // Resizes to a specific size as a temp buffer. No batches, no y-dim. + void Resize2d(bool int_mode, int width, int num_features, NetworkScratch *scratch) { + if (scratch_space_ == nullptr) { + int_mode_ = scratch->int_mode_ && int_mode; + scratch_space_ = scratch; + network_io_ = + int_mode_ ? scratch_space_->int_stack_.Borrow() : scratch_space_->float_stack_.Borrow(); + } + network_io_->Resize2d(int_mode, width, num_features); + } + // Resize forcing a float representation with the width of src and the given + // number of features. + void ResizeFloat(const NetworkIO &src, int num_features, NetworkScratch *scratch) { + if (scratch_space_ == nullptr) { + int_mode_ = false; + scratch_space_ = scratch; + network_io_ = scratch_space_->float_stack_.Borrow(); + } + network_io_->ResizeFloat(src, num_features); + } + + // Returns a ref to a NetworkIO that enables *this to be treated as if + // it were just a NetworkIO*. + NetworkIO &operator*() { + return *network_io_; + } + NetworkIO *operator->() { + return network_io_; + } + operator NetworkIO *() { + return network_io_; + } + + private: + // True if this is from the always-float stack, otherwise the default stack. + bool int_mode_; + // The NetworkIO that we have borrowed from the scratch_space_. + NetworkIO *network_io_; + // The source scratch_space_. Borrowed pointer, used to free the + // NetworkIO. Don't delete! + NetworkScratch *scratch_space_; + }; // class IO. + + // Class that acts like a fixed array of float, yet actually uses space + // from a vector<float> in the source NetworkScratch, and knows how + // to unstack the borrowed vector on destruction. + class FloatVec { + public: + // The array will have size elements in it, uninitialized. + FloatVec(int size, NetworkScratch *scratch) : vec_(nullptr), scratch_space_(scratch) { + Init(size, scratch); + } + // Default constructor is for arrays. Use Init to setup. + FloatVec() : vec_(nullptr), data_(nullptr), scratch_space_(nullptr) {} + ~FloatVec() { + if (scratch_space_ != nullptr) { + scratch_space_->vec_stack_.Return(vec_); + } + } + + void Init(int /*size*/, int reserve, NetworkScratch *scratch) { + if (scratch_space_ != nullptr && vec_ != nullptr) { + scratch_space_->vec_stack_.Return(vec_); + } + scratch_space_ = scratch; + vec_ = scratch_space_->vec_stack_.Borrow(); + // TODO: optimize. + vec_->resize(reserve); + data_ = &(*vec_)[0]; + } + + void Init(int size, NetworkScratch *scratch) { + Init(size, size, scratch); + } + + // Use the cast operator instead of operator[] so the FloatVec can be used + // as a TFloat* argument to a function call. + operator TFloat *() const { + return data_; + } + TFloat *get() { + return data_; + } + + private: + // Vector borrowed from the scratch space. Use Return to free it. + std::vector<TFloat> *vec_; + // Short-cut pointer to the underlying array. + TFloat *data_; + // The source scratch_space_. Borrowed pointer, used to free the + // vector. Don't delete! + NetworkScratch *scratch_space_; + }; // class FloatVec + + // Class that acts like a 2-D array of TFloat, yet actually uses space + // from the source NetworkScratch, and knows how to unstack the borrowed + // array on destruction. + class GradientStore { + public: + // Default constructor is for arrays. Use Init to setup. + GradientStore() : array_(nullptr), scratch_space_(nullptr) {} + ~GradientStore() { + if (scratch_space_ != nullptr) { + scratch_space_->array_stack_.Return(array_); + } + } + + void Init(int size1, int size2, NetworkScratch *scratch) { + if (scratch_space_ != nullptr && array_ != nullptr) { + scratch_space_->array_stack_.Return(array_); + } + scratch_space_ = scratch; + array_ = scratch_space_->array_stack_.Borrow(); + array_->Resize(size1, size2, 0.0); + } + + // Accessors to get to the underlying TransposedArray. + TransposedArray *get() const { + return array_; + } + const TransposedArray &operator*() const { + return *array_; + } + + private: + // Array borrowed from the scratch space. Use Return to free it. + TransposedArray *array_; + // The source scratch_space_. Borrowed pointer, used to free the + // vector. Don't delete! + NetworkScratch *scratch_space_; + }; // class GradientStore + + // Class that does the work of holding a stack of objects, a stack pointer + // and a vector of in-use flags, so objects can be returned out of order. + // It is safe to attempt to Borrow/Return in multiple threads. + template <typename T> + class Stack { + public: + Stack() = default; + + ~Stack() { + for (auto data : stack_) { + delete data; + } + } + + // Lends out the next free item, creating one if none available, sets + // the used flags and increments the stack top. + T *Borrow() { + std::lock_guard<std::mutex> lock(mutex_); + if (stack_top_ == stack_.size()) { + stack_.push_back(new T); + flags_.push_back(false); + } + flags_[stack_top_] = true; + return stack_[stack_top_++]; + } + // Takes back the given item, and marks it free. Item does not have to be + // the most recently lent out, but free slots don't get re-used until the + // blocking item is returned. The assumption is that there will only be + // small, temporary variations from true stack use. (Determined by the order + // of destructors within a local scope.) + void Return(T *item) { + std::lock_guard<std::mutex> lock(mutex_); + // Linear search will do. + int index = stack_top_; + while (--index >= 0 && stack_[index] != item) { + } + if (index >= 0) { + flags_[index] = false; + } + while (stack_top_ > 0 && !flags_[stack_top_ - 1]) { + --stack_top_; + } + } + + private: + std::vector<T *> stack_; + std::vector<bool> flags_; + unsigned stack_top_ = 0; + std::mutex mutex_; + }; // class Stack. + +private: + // If true, the network weights are int8_t, if false, float. + bool int_mode_; + // Stacks of NetworkIO and vector<float>. Once allocated, they are not + // deleted until the NetworkScratch is deleted. + Stack<NetworkIO> int_stack_; + Stack<NetworkIO> float_stack_; + Stack<std::vector<TFloat>> vec_stack_; + Stack<TransposedArray> array_stack_; +}; + +} // namespace tesseract. + +#endif // TESSERACT_LSTM_NETWORKSCRATCH_H_
