Files
Upsilon/apps/shared/function.h
Gabriel Ozouf a6db9688cd [apps/function] Factorize zoom in Function class
The new zoom implemented for ContinuousFunction is now factorized inside
Function to benefit the Sequence class. The same things is done to code
added to Graph::GraphController, which is moved into
FunctionGraphController.
This removes the reimplementation of several methods, most notably
computeYRange, as the implementation for function is general enough to
work on sequences.

Change-Id: I9b8211354064f46c3fa3dde3191dcb39d627a1d2
2020-11-04 15:30:53 +01:00

107 lines
4.2 KiB
C++

#ifndef SHARED_FUNCTION_H
#define SHARED_FUNCTION_H
#include <poincare/function.h>
#include <poincare/symbol.h>
#include <escher/i18n.h>
#include "expression_model_handle.h"
#if __EMSCRIPTEN__
#include <emscripten.h>
#endif
namespace Shared {
class Function : public ExpressionModelHandle {
public:
enum class NameNotCompliantError {
None = 0,
CharacterNotAllowed,
NameCannotStartWithNumber,
ReservedName
};
static NameNotCompliantError BaseNameCompliant(const char * baseName);
/* Possible arguments: n, x, t, θ
* The CodePoint θ is two char long. */
constexpr static int k_parenthesedArgumentCodePointLength = 3;
constexpr static int k_parenthesedThetaArgumentByteLength = 4;
constexpr static int k_parenthesedXNTArgumentByteLength = 3;
constexpr static int k_maxNameWithArgumentSize = Poincare::SymbolAbstract::k_maxNameSize + k_parenthesedThetaArgumentByteLength; /* Function name and null-terminating char + "(θ)" */;
// Constructors
Function(Ion::Storage::Record record) : ExpressionModelHandle(record){}
// Properties
bool isActive() const;
KDColor color() const;
void setActive(bool active);
// Definition Interval
virtual bool shouldClipTRangeToXRange() const { return true; } // Returns true if the function will not be displayed if t is outside x range.
virtual float tMin() const { return NAN; }
virtual float tMax() const { return NAN; }
virtual float rangeStep() const { return NAN; }
// Name
int name(char * buffer, size_t bufferSize);
int nameWithArgument(char * buffer, size_t bufferSize);
virtual int printValue(double cursorT, double cursorX, double cursorY, char * buffer, int bufferSize, int precision, Poincare::Context * context);
virtual I18n::Message parameterMessageName() const = 0;
// Evaluation
virtual Poincare::Coordinate2D<float> evaluateXYAtParameter(float t, Poincare::Context * context) const = 0;
virtual Poincare::Coordinate2D<double> evaluateXYAtParameter(double t, Poincare::Context * context) const = 0;
virtual Poincare::Expression sumBetweenBounds(double start, double end, Poincare::Context * context) const = 0;
// Range
virtual void rangeForDisplay(float * xMin, float * xMax, float * yMin, float * yMax, Poincare::Context * context, bool tuneXRange = true) const;
protected:
/* RecordDataBuffer is the layout of the data buffer of Record
* representing a Function. We want to avoid padding which would:
* - increase the size of the storage file
* - introduce junk memory zone which are then crc-ed in Storage::checksum
* creating dependency on uninitialized values.
* - complicate getters, setters and record handling
* In addition, Record::value() is a pointer to an address inside
* Ion::Storage::sharedStorage(), and it might be unaligned. We use the packed
* keyword to warn the compiler that it members are potentially unaligned
* (otherwise, the compiler can emit instructions that work only on aligned
* objects). It also solves the padding issue mentioned above.
*/
class __attribute__((packed)) RecordDataBuffer {
public:
RecordDataBuffer(KDColor color) : m_color(color), m_active(true) {}
KDColor color() const {
return KDColor::RGB16(m_color);
}
bool isActive() const { return m_active; }
void setActive(bool active) { m_active = active; }
private:
#if __EMSCRIPTEN__
/* For emscripten memory representation, loads and stores must be aligned;
* performing a normal load or store on an unaligned address can fail
* silently. We thus use 'emscripten_align1_short' type, the unaligned
* version of uint16_t type to avoid producing an alignment error on the
* emscripten platform. */
static_assert(sizeof(emscripten_align1_short) == sizeof(uint16_t), "emscripten_align1_short should have the same size as uint16_t");
emscripten_align1_short m_color;
#else
uint16_t m_color;
#endif
bool m_active;
};
void protectedRefinedYRangeForDisplay(float xMin, float xMax, float * yMin, float * yMax, Poincare::Context * context, bool boundByMagnitude) const;
private:
virtual void refinedYRangeForDisplay(float xMin, float xMax, float * yMin, float * yMax, Poincare::Context * context) const = 0;
RecordDataBuffer * recordData() const;
};
}
#endif